vendor: 9,492 bytes, lines 1-385
1/*! 2 * jQuery JavaScript Library v3.4.1 3 * https://jquery.com/ 4 * 5 * Includes Sizzle.js 6 * https://sizzlejs.com/ 7 * 8 * Copyright JS Foundation and other contributors 9 * Released under the MIT license 10 * https://jquery.org/license 11 * 12 * Date: 2019-05-01T21:04Z 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 #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 document = window.document; 51 52var getProto = Object.getPrototypeOf; 53 54var slice = arr.slice; 55 56var concat = arr.concat; 57 58var push = arr.push; 59 60var indexOf = arr.indexOf; 61 62var class2type = {}; 63 64var toString = class2type.toString; 65 66var hasOwn = class2type.hasOwnProperty; 67 68var fnToString = hasOwn.toString; 69 70var ObjectFunctionString = fnToString.call( Object ); 71 72var support = {}; 73 74var isFunction = function isFunction( obj ) { 75 76 // Support: Chrome <=57, Firefox <=52 77 // In some browsers, typeof returns "function" for HTML <object> elements 78 // (i.e., `typeof document.createElement( "object" ) === "function"`). 79 // We don't want to classify *any* DOM node as a function. 80 return typeof obj === "function" && typeof obj.nodeType !== "number"; 81 }; 82 83 84var isWindow = function isWindow( obj ) { 85 return obj != null && obj === obj.window; 86 }; 87 88 89 90 91 var preservedScriptAttributes = { 92 type: true, 93 src: true, 94 nonce: true, 95 noModule: true 96 }; 97 98 function DOMEval( code, node, doc ) { 99 doc = doc || document; 100 101 var i, val, 102 script = doc.createElement( "script" ); 103 104 script.text = code; 105 if ( node ) { 106 for ( i in preservedScriptAttributes ) { 107 108 // Support: Firefox 64+, Edge 18+ 109 // Some browsers don't support the "nonce" property on scripts. 110 // On the other hand, just using `getAttribute` is not enough as 111 // the `nonce` attribute is reset to an empty string whenever it 112 // becomes browsing-context connected. 113 // See https://github.com/whatwg/html/issues/2369 114 // See https://html.spec.whatwg.org/#nonce-attributes 115 // The `node.getAttribute` check was added for the sake of 116 // `jQuery.globalEval` so that it can fake a nonce-containing node 117 // via an object. 118 val = node[ i ] || node.getAttribute && node.getAttribute( i ); 119 if ( val ) { 120 script.setAttribute( i, val ); 121 } 122 } 123 } 124 doc.head.appendChild( script ).parentNode.removeChild( script ); 125 } 126 127 128function toType( obj ) { 129 if ( obj == null ) { 130 return obj + ""; 131 } 132 133 // Support: Android <=2.3 only (functionish RegExp) 134 return typeof obj === "object" || typeof obj === "function" ? 135 class2type[ toString.call( obj ) ] || "object" : 136 typeof obj; 137} 138/* global Symbol */ 139// Defining this global in .eslintrc.json would create a danger of using the global 140// unguarded in another place, it seems safer to define global only for this module 141 142 143 144var 145 version = "3.4.1", 146 147 // Define a local copy of jQuery 148 jQuery = function( selector, context ) { 149 150 // The jQuery object is actually just the init constructor 'enhanced' 151 // Need init if jQuery is called (just allow error to be thrown if not included) 152 return new jQuery.fn.init( selector, context ); 153 }, 154 155 // Support: Android <=4.0 only 156 // Make sure we trim BOM and NBSP 157 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; 158 159jQuery.fn = jQuery.prototype = { 160 161 // The current version of jQuery being used 162 jquery: version, 163 164 constructor: jQuery, 165 166 // The default length of a jQuery object is 0 167 length: 0, 168 169 toArray: function() { 170 return slice.call( this ); 171 }, 172 173 // Get the Nth element in the matched element set OR 174 // Get the whole matched element set as a clean array 175 get: function( num ) { 176 177 // Return all the elements in a clean array 178 if ( num == null ) { 179 return slice.call( this ); 180 } 181 182 // Return just the one element from the set 183 return num < 0 ? this[ num + this.length ] : this[ num ]; 184 }, 185 186 // Take an array of elements and push it onto the stack 187 // (returning the new matched element set) 188 pushStack: function( elems ) { 189 190 // Build a new jQuery matched element set 191 var ret = jQuery.merge( this.constructor(), elems ); 192 193 // Add the old object onto the stack (as a reference) 194 ret.prevObject = this; 195 196 // Return the newly-formed element set 197 return ret; 198 }, 199 200 // Execute a callback for every element in the matched set. 201 each: function( callback ) { 202 return jQuery.each( this, callback ); 203 }, 204 205 map: function( callback ) { 206 return this.pushStack( jQuery.map( this, function( elem, i ) { 207 return callback.call( elem, i, elem ); 208 } ) ); 209 }, 210 211 slice: function() { 212 return this.pushStack( slice.apply( this, arguments ) ); 213 }, 214 215 first: function() { 216 return this.eq( 0 ); 217 }, 218 219 last: function() { 220 return this.eq( -1 ); 221 }, 222 223 eq: function( i ) { 224 var len = this.length, 225 j = +i + ( i < 0 ? len : 0 ); 226 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); 227 }, 228 229 end: function() { 230 return this.prevObject || this.constructor(); 231 }, 232 233 // For internal use only. 234 // Behaves like an Array's method, not like a jQuery method. 235 push: push, 236 sort: arr.sort, 237 splice: arr.splice 238}; 239 240jQuery.extend = jQuery.fn.extend = function() { 241 var options, name, src, copy, copyIsArray, clone, 242 target = arguments[ 0 ] || {}, 243 i = 1, 244 length = arguments.length, 245 deep = false; 246 247 // Handle a deep copy situation 248 if ( typeof target === "boolean" ) { 249 deep = target; 250 251 // Skip the boolean and the target 252 target = arguments[ i ] || {}; 253 i++; 254 } 255 256 // Handle case when target is a string or something (possible in deep copy) 257 if ( typeof target !== "object" && !isFunction( target ) ) { 258 target = {}; 259 } 260 261 // Extend jQuery itself if only one argument is passed 262 if ( i === length ) { 263 target = this; 264 i--; 265 } 266 267 for ( ; i < length; i++ ) { 268 269 // Only deal with non-null/undefined values 270 if ( ( options = arguments[ i ] ) != null ) { 271 272 // Extend the base object 273 for ( name in options ) { 274 copy = options[ name ]; 275 276 // Prevent Object.prototype pollution 277 // Prevent never-ending loop 278 if ( name === "__proto__" || target === copy ) { 279 continue; 280 } 281 282 // Recurse if we're merging plain objects or arrays 283 if ( deep && copy && ( jQuery.isPlainObject( copy ) || 284 ( copyIsArray = Array.isArray( copy ) ) ) ) { 285 src = target[ name ]; 286 287 // Ensure proper type for the source value 288 if ( copyIsArray && !Array.isArray( src ) ) { 289 clone = []; 290 } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { 291 clone = {}; 292 } else { 293 clone = src; 294 } 295 copyIsArray = false; 296 297 // Never move original objects, clone them 298 target[ name ] = jQuery.extend( deep, clone, copy ); 299 300 // Don't bring in undefined values 301 } else if ( copy !== undefined ) { 302 target[ name ] = copy; 303 } 304 } 305 } 306 } 307 308 // Return the modified object 309 return target; 310}; 311 312jQuery.extend( { 313 314 // Unique for each copy of jQuery on the page 315 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 316 317 // Assume jQuery is ready without the ready module 318 isReady: true, 319 320 error: function( msg ) { 321 throw new Error( msg ); 322 }, 323 324 noop: function() {}, 325 326 isPlainObject: function( obj ) { 327 var proto, Ctor; 328 329 // Detect obvious negatives 330 // Use toString instead of jQuery.type to catch host objects 331 if ( !obj || toString.call( obj ) !== "[object Object]" ) { 332 return false; 333 } 334 335 proto = getProto( obj ); 336 337 // Objects with no prototype (e.g., `Object.create( null )`) are plain 338 if ( !proto ) { 339 return true; 340 } 341 342 // Objects with prototype are plain iff they were constructed by a global Object function 343 Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; 344 return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; 345 }, 346 347 isEmptyObject: function( obj ) { 348 var name; 349 350 for ( name in obj ) { 351 return false; 352 } 353 return true; 354 }, 355 356 // Evaluates a script in a global context 357 globalEval: function( code, options ) { 358 DOMEval( code, { nonce: options && options.nonce } ); 359 }, 360 361 each: function( obj, callback ) { 362 var length, i = 0; 363 364 if ( isArrayLike( obj ) ) { 365 length = obj.length; 366 for ( ; i < length; i++ ) { 367 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 368 break; 369 } 370 } 371 } else { 372 for ( i in obj ) { 373 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 374 break; 375 } 376 } 377 } 378 379 return obj; 380 }, 381 382 // Support: Android <=4.0 only 383 trim: function( text ) { 384 return text == null ? 385 "" :
vendor: 14,126 bytes, lines 386-904
386 ( text + "" ).replace( rtrim, "" ); 387 }, 388 389 // results is for internal usage only 390 makeArray: function( arr, results ) { 391 var ret = results || []; 392 393 if ( arr != null ) { 394 if ( isArrayLike( Object( arr ) ) ) { 395 jQuery.merge( ret, 396 typeof arr === "string" ? 397 [ arr ] : arr 398 ); 399 } else { 400 push.call( ret, arr ); 401 } 402 } 403 404 return ret; 405 }, 406 407 inArray: function( elem, arr, i ) { 408 return arr == null ? -1 : indexOf.call( arr, elem, i ); 409 }, 410 411 // Support: Android <=4.0 only, PhantomJS 1 only 412 // push.apply(_, arraylike) throws on ancient WebKit 413 merge: function( first, second ) { 414 var len = +second.length, 415 j = 0, 416 i = first.length; 417 418 for ( ; j < len; j++ ) { 419 first[ i++ ] = second[ j ]; 420 } 421 422 first.length = i; 423 424 return first; 425 }, 426 427 grep: function( elems, callback, invert ) { 428 var callbackInverse, 429 matches = [], 430 i = 0, 431 length = elems.length, 432 callbackExpect = !invert; 433 434 // Go through the array, only saving the items 435 // that pass the validator function 436 for ( ; i < length; i++ ) { 437 callbackInverse = !callback( elems[ i ], i ); 438 if ( callbackInverse !== callbackExpect ) { 439 matches.push( elems[ i ] ); 440 } 441 } 442 443 return matches; 444 }, 445 446 // arg is for internal usage only 447 map: function( elems, callback, arg ) { 448 var length, value, 449 i = 0, 450 ret = []; 451 452 // Go through the array, translating each of the items to their new values 453 if ( isArrayLike( elems ) ) { 454 length = elems.length; 455 for ( ; i < length; i++ ) { 456 value = callback( elems[ i ], i, arg ); 457 458 if ( value != null ) { 459 ret.push( value ); 460 } 461 } 462 463 // Go through every key on the object, 464 } else { 465 for ( i in elems ) { 466 value = callback( elems[ i ], i, arg ); 467 468 if ( value != null ) { 469 ret.push( value ); 470 } 471 } 472 } 473 474 // Flatten any nested arrays 475 return concat.apply( [], ret ); 476 }, 477 478 // A global GUID counter for objects 479 guid: 1, 480 481 // jQuery.support is not used in Core but other projects attach their 482 // properties to it so it needs to exist. 483 support: support 484} ); 485 486if ( typeof Symbol === "function" ) { 487 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; 488} 489 490// Populate the class2type map 491jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 492function( i, name ) { 493 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 494} ); 495 496function isArrayLike( obj ) { 497 498 // Support: real iOS 8.2 only (not reproducible in simulator) 499 // `in` check used to prevent JIT error (gh-2145) 500 // hasOwn isn't used here due to false negatives 501 // regarding Nodelist length in IE 502 var length = !!obj && "length" in obj && obj.length, 503 type = toType( obj ); 504 505 if ( isFunction( obj ) || isWindow( obj ) ) { 506 return false; 507 } 508 509 return type === "array" || length === 0 || 510 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 511} 512var Sizzle = 513/*! 514 * Sizzle CSS Selector Engine v2.3.4 515 * https://sizzlejs.com/ 516 * 517 * Copyright JS Foundation and other contributors 518 * Released under the MIT license 519 * https://js.foundation/ 520 * 521 * Date: 2019-04-08 522 */ 523(function( window ) { 524 525var i, 526 support, 527 Expr, 528 getText, 529 isXML, 530 tokenize, 531 compile, 532 select, 533 outermostContext, 534 sortInput, 535 hasDuplicate, 536 537 // Local document vars 538 setDocument, 539 document, 540 docElem, 541 documentIsHTML, 542 rbuggyQSA, 543 rbuggyMatches, 544 matches, 545 contains, 546 547 // Instance-specific data 548 expando = "sizzle" + 1 * new Date(), 549 preferredDoc = window.document, 550 dirruns = 0, 551 done = 0, 552 classCache = createCache(), 553 tokenCache = createCache(), 554 compilerCache = createCache(), 555 nonnativeSelectorCache = createCache(), 556 sortOrder = function( a, b ) { 557 if ( a === b ) { 558 hasDuplicate = true; 559 } 560 return 0; 561 }, 562 563 // Instance methods 564 hasOwn = ({}).hasOwnProperty, 565 arr = [], 566 pop = arr.pop, 567 push_native = arr.push, 568 push = arr.push, 569 slice = arr.slice, 570 // Use a stripped-down indexOf as it's faster than native 571 // https://jsperf.com/thor-indexof-vs-for/5 572 indexOf = function( list, elem ) { 573 var i = 0, 574 len = list.length; 575 for ( ; i < len; i++ ) { 576 if ( list[i] === elem ) { 577 return i; 578 } 579 } 580 return -1; 581 }, 582 583 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 584 585 // Regular expressions 586 587 // http://www.w3.org/TR/css3-selectors/#whitespace 588 whitespace = "[\\x20\\t\\r\\n\\f]", 589 590 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 591 identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", 592 593 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors 594 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + 595 // Operator (capture 2) 596 "*([*^$|!~]?=)" + whitespace + 597 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 598 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + 599 "*\\]", 600 601 pseudos = ":(" + identifier + ")(?:\\((" + 602 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 603 // 1. quoted (capture 3; capture 4 or capture 5) 604 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + 605 // 2. simple (capture 6) 606 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + 607 // 3. anything else (capture 2) 608 ".*" + 609 ")\\)|)", 610 611 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 612 rwhitespace = new RegExp( whitespace + "+", "g" ), 613 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 614 615 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 616 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 617 rdescend = new RegExp( whitespace + "|>" ), 618 619 rpseudo = new RegExp( pseudos ), 620 ridentifier = new RegExp( "^" + identifier + "$" ), 621 622 matchExpr = { 623 "ID": new RegExp( "^#(" + identifier + ")" ), 624 "CLASS": new RegExp( "^\\.(" + identifier + ")" ), 625 "TAG": new RegExp( "^(" + identifier + "|[*])" ), 626 "ATTR": new RegExp( "^" + attributes ), 627 "PSEUDO": new RegExp( "^" + pseudos ), 628 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 629 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 630 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 631 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 632 // For use in libraries implementing .is() 633 // We use this for POS matching in `select` 634 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 635 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 636 }, 637 638 rhtml = /HTML$/i, 639 rinputs = /^(?:input|select|textarea|button)$/i, 640 rheader = /^h\d$/i, 641 642 rnative = /^[^{]+\{\s*\[native \w/, 643 644 // Easily-parseable/retrievable ID or TAG or CLASS selectors 645 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 646 647 rsibling = /[+~]/, 648 649 // CSS escapes 650 // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 651 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 652 funescape = function( _, escaped, escapedWhitespace ) { 653 var high = "0x" + escaped - 0x10000; 654 // NaN means non-codepoint 655 // Support: Firefox<24 656 // Workaround erroneous numeric interpretation of +"0x" 657 return high !== high || escapedWhitespace ? 658 escaped : 659 high < 0 ? 660 // BMP codepoint 661 String.fromCharCode( high + 0x10000 ) : 662 // Supplemental Plane codepoint (surrogate pair) 663 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 664 }, 665 666 // CSS string/identifier serialization 667 // https://drafts.csswg.org/cssom/#common-serializing-idioms 668 rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, 669 fcssescape = function( ch, asCodePoint ) { 670 if ( asCodePoint ) { 671 672 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER 673 if ( ch === "\0" ) { 674 return "\uFFFD"; 675 } 676 677 // Control characters and (dependent upon position) numbers get escaped as code points 678 return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; 679 } 680 681 // Other potentially-special ASCII characters get backslash-escaped 682 return "\\" + ch; 683 }, 684 685 // Used for iframes 686 // See setDocument() 687 // Removing the function wrapper causes a "Permission Denied" 688 // error in IE 689 unloadHandler = function() { 690 setDocument(); 691 }, 692 693 inDisabledFieldset = addCombinator( 694 function( elem ) { 695 return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; 696 }, 697 { dir: "parentNode", next: "legend" } 698 ); 699 700// Optimize for push.apply( _, NodeList ) 701try { 702 push.apply( 703 (arr = slice.call( preferredDoc.childNodes )), 704 preferredDoc.childNodes 705 ); 706 // Support: Android<4.0 707 // Detect silently failing push.apply 708 arr[ preferredDoc.childNodes.length ].nodeType; 709} catch ( e ) { 710 push = { apply: arr.length ? 711 712 // Leverage slice if possible 713 function( target, els ) { 714 push_native.apply( target, slice.call(els) ); 715 } : 716 717 // Support: IE<9 718 // Otherwise append directly 719 function( target, els ) { 720 var j = target.length, 721 i = 0; 722 // Can't trust NodeList.length 723 while ( (target[j++] = els[i++]) ) {} 724 target.length = j - 1; 725 } 726 }; 727} 728 729function Sizzle( selector, context, results, seed ) { 730 var m, i, elem, nid, match, groups, newSelector, 731 newContext = context && context.ownerDocument, 732 733 // nodeType defaults to 9, since context defaults to document 734 nodeType = context ? context.nodeType : 9; 735 736 results = results || []; 737 738 // Return early from calls with invalid selector or context 739 if ( typeof selector !== "string" || !selector || 740 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { 741 742 return results; 743 } 744 745 // Try to shortcut find operations (as opposed to filters) in HTML documents 746 if ( !seed ) { 747 748 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 749 setDocument( context ); 750 } 751 context = context || document; 752 753 if ( documentIsHTML ) { 754 755 // If the selector is sufficiently simple, try using a "get*By*" DOM method 756 // (excepting DocumentFragment context, where the methods don't exist) 757 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { 758 759 // ID selector 760 if ( (m = match[1]) ) { 761 762 // Document context 763 if ( nodeType === 9 ) { 764 if ( (elem = context.getElementById( m )) ) { 765 766 // Support: IE, Opera, Webkit 767 // TODO: identify versions 768 // getElementById can match elements by name instead of ID 769 if ( elem.id === m ) { 770 results.push( elem ); 771 return results; 772 } 773 } else { 774 return results; 775 } 776 777 // Element context 778 } else { 779 780 // Support: IE, Opera, Webkit 781 // TODO: identify versions 782 // getElementById can match elements by name instead of ID 783 if ( newContext && (elem = newContext.getElementById( m )) && 784 contains( context, elem ) && 785 elem.id === m ) { 786 787 results.push( elem ); 788 return results; 789 } 790 } 791 792 // Type selector 793 } else if ( match[2] ) { 794 push.apply( results, context.getElementsByTagName( selector ) ); 795 return results; 796 797 // Class selector 798 } else if ( (m = match[3]) && support.getElementsByClassName && 799 context.getElementsByClassName ) { 800 801 push.apply( results, context.getElementsByClassName( m ) ); 802 return results; 803 } 804 } 805 806 // Take advantage of querySelectorAll 807 if ( support.qsa && 808 !nonnativeSelectorCache[ selector + " " ] && 809 (!rbuggyQSA || !rbuggyQSA.test( selector )) && 810 811 // Support: IE 8 only 812 // Exclude object elements 813 (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) { 814 815 newSelector = selector; 816 newContext = context; 817 818 // qSA considers elements outside a scoping root when evaluating child or 819 // descendant combinators, which is not what we want. 820 // In such cases, we work around the behavior by prefixing every selector in the 821 // list with an ID selector referencing the scope context. 822 // Thanks to Andrew Dupont for this technique. 823 if ( nodeType === 1 && rdescend.test( selector ) ) { 824 825 // Capture the context ID, setting it first if necessary 826 if ( (nid = context.getAttribute( "id" )) ) { 827 nid = nid.replace( rcssescape, fcssescape ); 828 } else { 829 context.setAttribute( "id", (nid = expando) ); 830 } 831 832 // Prefix every selector in the list 833 groups = tokenize( selector ); 834 i = groups.length; 835 while ( i-- ) { 836 groups[i] = "#" + nid + " " + toSelector( groups[i] ); 837 } 838 newSelector = groups.join( "," ); 839 840 // Expand context for sibling selectors 841 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || 842 context; 843 } 844 845 try { 846 push.apply( results, 847 newContext.querySelectorAll( newSelector ) 848 ); 849 return results; 850 } catch ( qsaError ) { 851 nonnativeSelectorCache( selector, true ); 852 } finally { 853 if ( nid === expando ) { 854 context.removeAttribute( "id" ); 855 } 856 } 857 } 858 } 859 } 860 861 // All others 862 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 863} 864 865/** 866 * Create key-value caches of limited size 867 * @returns {function(string, object)} Returns the Object data after storing it on itself with 868 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 869 * deleting the oldest entry 870 */ 871function createCache() { 872 var keys = []; 873 874 function cache( key, value ) { 875 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 876 if ( keys.push( key + " " ) > Expr.cacheLength ) { 877 // Only keep the most recent entries 878 delete cache[ keys.shift() ]; 879 } 880 return (cache[ key + " " ] = value); 881 } 882 return cache; 883} 884 885/** 886 * Mark a function for special use by Sizzle 887 * @param {Function} fn The function to mark 888 */ 889function markFunction( fn ) { 890 fn[ expando ] = true; 891 return fn; 892} 893 894/** 895 * Support testing using an element 896 * @param {Function} fn Passed the created element and returns a boolean result 897 */ 898function assert( fn ) { 899 var el = document.createElement("fieldset"); 900 901 try { 902 return !!fn( el ); 903 } catch (e) { 904 return false;
905 } finally { 906 // Remove from its parent by default 907 if ( el.parentNode ) { 908 el.parentNode.removeChild( el ); 909 } 910 // release memory in IE 911 el = null; 912 } 913} 914 915/** 916 * Adds the same handler for all of the specified attrs 917 * @param {String} attrs Pipe-separated list of attributes 918 * @param {Function} handler The method that will be applied 919 */ 920function addHandle( attrs, handler ) { 921 var arr = attrs.split("|"), 922 i = arr.length; 923 924 while ( i-- ) { 925 Expr.attrHandle[ arr[i] ] = handler; 926 } 927} 928 929/** 930 * Checks document order of two siblings 931 * @param {Element} a 932 * @param {Element} b 933 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 934 */ 935function siblingCheck( a, b ) { 936 var cur = b && a, 937 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 938 a.sourceIndex - b.sourceIndex; 939 940 // Use IE sourceIndex if available on both nodes 941 if ( diff ) { 942 return diff; 943 } 944 945 // Check if b follows a 946 if ( cur ) { 947 while ( (cur = cur.nextSibling) ) { 948 if ( cur === b ) { 949 return -1; 950 } 951 } 952 } 953 954 return a ? 1 : -1; 955} 956 957/** 958 * Returns a function to use in pseudos for input types 959 * @param {String} type 960 */ 961function createInputPseudo( type ) { 962 return function( elem ) { 963 var name = elem.nodeName.toLowerCase(); 964 return name === "input" && elem.type === type; 965 }; 966} 967 968/** 969 * Returns a function to use in pseudos for buttons 970 * @param {String} type 971 */ 972function createButtonPseudo( type ) { 973 return function( elem ) { 974 var name = elem.nodeName.toLowerCase(); 975 return (name === "input" || name === "button") && elem.type === type; 976 }; 977} 978 979/** 980 * Returns a function to use in pseudos for :enabled/:disabled 981 * @param {Boolean} disabled true for :disabled; false for :enabled 982 */ 983function createDisabledPseudo( disabled ) { 984 985 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable 986 return function( elem ) { 987 988 // Only certain elements can match :enabled or :disabled 989 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled 990 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled 991 if ( "form" in elem ) { 992 993 // Check for inherited disabledness on relevant non-disabled elements: 994 // * listed form-associated elements in a disabled fieldset 995 // https://html.spec.whatwg.org/multipage/forms.html#category-listed 996 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled 997 // * option elements in a disabled optgroup 998 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled 999 // All such elements have a "form" property. 1000 if ( elem.parentNode && elem.disabled === false ) { 1001 1002 // Option elements defer to a parent optgroup if present 1003 if ( "label" in elem ) { 1004 if ( "label" in elem.parentNode ) { 1005 return elem.parentNode.disabled === disabled; 1006 } else { 1007 return elem.disabled === disabled; 1008 } 1009 } 1010 1011 // Support: IE 6 - 11 1012 // Use the isDisabled shortcut property to check for disabled fieldset ancestors 1013 return elem.isDisabled === disabled || 1014 1015 // Where there is no isDisabled, check manually 1016 /* jshint -W018 */ 1017 elem.isDisabled !== !disabled && 1018 inDisabledFieldset( elem ) === disabled; 1019 } 1020 1021 return elem.disabled === disabled; 1022 1023 // Try to winnow out elements that can't be disabled before trusting the disabled property. 1024 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't 1025 // even exist on them, let alone have a boolean value. 1026 } else if ( "label" in elem ) { 1027 return elem.disabled === disabled; 1028 } 1029 1030 // Remaining elements are neither :enabled nor :disabled 1031 return false; 1032 }; 1033} 1034 1035/** 1036 * Returns a function to use in pseudos for positionals 1037 * @param {Function} fn 1038 */ 1039function createPositionalPseudo( fn ) { 1040 return markFunction(function( argument ) { 1041 argument = +argument; 1042 return markFunction(function( seed, matches ) { 1043 var j, 1044 matchIndexes = fn( [], seed.length, argument ), 1045 i = matchIndexes.length; 1046 1047 // Match elements found at the specified indexes 1048 while ( i-- ) { 1049 if ( seed[ (j = matchIndexes[i]) ] ) { 1050 seed[j] = !(matches[j] = seed[j]); 1051 } 1052 } 1053 }); 1054 }); 1055} 1056 1057/** 1058 * Checks a node for validity as a Sizzle context
vendor: 13,957 bytes, lines 1059-1520
1059 * @param {Element|Object=} context 1060 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 1061 */ 1062function testContext( context ) { 1063 return context && typeof context.getElementsByTagName !== "undefined" && context; 1064} 1065 1066// Expose support vars for convenience 1067support = Sizzle.support = {}; 1068 1069/** 1070 * Detects XML nodes 1071 * @param {Element|Object} elem An element or a document 1072 * @returns {Boolean} True iff elem is a non-HTML XML node 1073 */ 1074isXML = Sizzle.isXML = function( elem ) { 1075 var namespace = elem.namespaceURI, 1076 docElem = (elem.ownerDocument || elem).documentElement; 1077 1078 // Support: IE <=8 1079 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes 1080 // https://bugs.jquery.com/ticket/4833 1081 return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); 1082}; 1083 1084/** 1085 * Sets document-related variables once based on the current document 1086 * @param {Element|Object} [doc] An element or document object to use to set the document 1087 * @returns {Object} Returns the current document 1088 */ 1089setDocument = Sizzle.setDocument = function( node ) { 1090 var hasCompare, subWindow, 1091 doc = node ? node.ownerDocument || node : preferredDoc; 1092 1093 // Return early if doc is invalid or already selected 1094 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 1095 return document; 1096 } 1097 1098 // Update global variables 1099 document = doc; 1100 docElem = document.documentElement; 1101 documentIsHTML = !isXML( document ); 1102 1103 // Support: IE 9-11, Edge 1104 // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) 1105 if ( preferredDoc !== document && 1106 (subWindow = document.defaultView) && subWindow.top !== subWindow ) { 1107 1108 // Support: IE 11, Edge 1109 if ( subWindow.addEventListener ) { 1110 subWindow.addEventListener( "unload", unloadHandler, false ); 1111 1112 // Support: IE 9 - 10 only 1113 } else if ( subWindow.attachEvent ) { 1114 subWindow.attachEvent( "onunload", unloadHandler ); 1115 } 1116 } 1117 1118 /* Attributes 1119 ---------------------------------------------------------------------- */ 1120 1121 // Support: IE<8 1122 // Verify that getAttribute really returns attributes and not properties 1123 // (excepting IE8 booleans) 1124 support.attributes = assert(function( el ) { 1125 el.className = "i"; 1126 return !el.getAttribute("className"); 1127 }); 1128 1129 /* getElement(s)By* 1130 ---------------------------------------------------------------------- */ 1131 1132 // Check if getElementsByTagName("*") returns only elements 1133 support.getElementsByTagName = assert(function( el ) { 1134 el.appendChild( document.createComment("") ); 1135 return !el.getElementsByTagName("*").length; 1136 }); 1137 1138 // Support: IE<9 1139 support.getElementsByClassName = rnative.test( document.getElementsByClassName ); 1140 1141 // Support: IE<10 1142 // Check if getElementById returns elements by name 1143 // The broken getElementById methods don't pick up programmatically-set names, 1144 // so use a roundabout getElementsByName test 1145 support.getById = assert(function( el ) { 1146 docElem.appendChild( el ).id = expando; 1147 return !document.getElementsByName || !document.getElementsByName( expando ).length; 1148 }); 1149 1150 // ID filter and find 1151 if ( support.getById ) { 1152 Expr.filter["ID"] = function( id ) { 1153 var attrId = id.replace( runescape, funescape ); 1154 return function( elem ) { 1155 return elem.getAttribute("id") === attrId; 1156 }; 1157 }; 1158 Expr.find["ID"] = function( id, context ) { 1159 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1160 var elem = context.getElementById( id ); 1161 return elem ? [ elem ] : []; 1162 } 1163 }; 1164 } else { 1165 Expr.filter["ID"] = function( id ) { 1166 var attrId = id.replace( runescape, funescape ); 1167 return function( elem ) { 1168 var node = typeof elem.getAttributeNode !== "undefined" && 1169 elem.getAttributeNode("id"); 1170 return node && node.value === attrId; 1171 }; 1172 }; 1173 1174 // Support: IE 6 - 7 only 1175 // getElementById is not reliable as a find shortcut 1176 Expr.find["ID"] = function( id, context ) { 1177 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1178 var node, i, elems, 1179 elem = context.getElementById( id ); 1180 1181 if ( elem ) { 1182 1183 // Verify the id attribute 1184 node = elem.getAttributeNode("id"); 1185 if ( node && node.value === id ) { 1186 return [ elem ]; 1187 } 1188 1189 // Fall back on getElementsByName 1190 elems = context.getElementsByName( id ); 1191 i = 0; 1192 while ( (elem = elems[i++]) ) { 1193 node = elem.getAttributeNode("id"); 1194 if ( node && node.value === id ) { 1195 return [ elem ]; 1196 } 1197 } 1198 } 1199 1200 return []; 1201 } 1202 }; 1203 } 1204 1205 // Tag 1206 Expr.find["TAG"] = support.getElementsByTagName ? 1207 function( tag, context ) { 1208 if ( typeof context.getElementsByTagName !== "undefined" ) { 1209 return context.getElementsByTagName( tag ); 1210 1211 // DocumentFragment nodes don't have gEBTN 1212 } else if ( support.qsa ) { 1213 return context.querySelectorAll( tag ); 1214 } 1215 } : 1216 1217 function( tag, context ) { 1218 var elem, 1219 tmp = [], 1220 i = 0, 1221 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too 1222 results = context.getElementsByTagName( tag ); 1223 1224 // Filter out possible comments 1225 if ( tag === "*" ) { 1226 while ( (elem = results[i++]) ) { 1227 if ( elem.nodeType === 1 ) { 1228 tmp.push( elem ); 1229 } 1230 } 1231 1232 return tmp; 1233 } 1234 return results; 1235 }; 1236 1237 // Class 1238 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 1239 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { 1240 return context.getElementsByClassName( className ); 1241 } 1242 }; 1243 1244 /* QSA/matchesSelector 1245 ---------------------------------------------------------------------- */ 1246 1247 // QSA and matchesSelector support 1248 1249 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 1250 rbuggyMatches = []; 1251 1252 // qSa(:focus) reports false when true (Chrome 21) 1253 // We allow this because of a bug in IE8/9 that throws an error 1254 // whenever `document.activeElement` is accessed on an iframe 1255 // So, we allow :focus to pass through QSA all the time to avoid the IE error 1256 // See https://bugs.jquery.com/ticket/13378 1257 rbuggyQSA = []; 1258 1259 if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { 1260 // Build QSA regex 1261 // Regex strategy adopted from Diego Perini 1262 assert(function( el ) { 1263 // Select is set to empty string on purpose 1264 // This is to test IE's treatment of not explicitly 1265 // setting a boolean content attribute, 1266 // since its presence should be enough 1267 // https://bugs.jquery.com/ticket/12359 1268 docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" + 1269 "<select id='" + expando + "-\r\\' msallowcapture=''>" + 1270 "<option selected=''></option></select>"; 1271 1272 // Support: IE8, Opera 11-12.16 1273 // Nothing should be selected when empty strings follow ^= or $= or *= 1274 // The test attribute must be unknown in Opera but "safe" for WinRT 1275 // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section 1276 if ( el.querySelectorAll("[msallowcapture^='']").length ) { 1277 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 1278 } 1279 1280 // Support: IE8 1281 // Boolean attributes and "value" are not treated correctly 1282 if ( !el.querySelectorAll("[selected]").length ) { 1283 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 1284 } 1285 1286 // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ 1287 if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { 1288 rbuggyQSA.push("~="); 1289 } 1290 1291 // Webkit/Opera - :checked should return selected option elements 1292 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1293 // IE8 throws error here and will not see later tests 1294 if ( !el.querySelectorAll(":checked").length ) { 1295 rbuggyQSA.push(":checked"); 1296 } 1297 1298 // Support: Safari 8+, iOS 8+ 1299 // https://bugs.webkit.org/show_bug.cgi?id=136851 1300 // In-page `selector#id sibling-combinator selector` fails 1301 if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { 1302 rbuggyQSA.push(".#.+[+~]"); 1303 } 1304 }); 1305 1306 assert(function( el ) { 1307 el.innerHTML = "<a href='' disabled='disabled'></a>" + 1308 "<select disabled='disabled'><option/></select>"; 1309 1310 // Support: Windows 8 Native Apps 1311 // The type and name attributes are restricted during .innerHTML assignment 1312 var input = document.createElement("input"); 1313 input.setAttribute( "type", "hidden" ); 1314 el.appendChild( input ).setAttribute( "name", "D" ); 1315 1316 // Support: IE8 1317 // Enforce case-sensitivity of name attribute 1318 if ( el.querySelectorAll("[name=d]").length ) { 1319 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 1320 } 1321 1322 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 1323 // IE8 throws error here and will not see later tests 1324 if ( el.querySelectorAll(":enabled").length !== 2 ) { 1325 rbuggyQSA.push( ":enabled", ":disabled" ); 1326 } 1327 1328 // Support: IE9-11+ 1329 // IE's :disabled selector does not pick up the children of disabled fieldsets 1330 docElem.appendChild( el ).disabled = true; 1331 if ( el.querySelectorAll(":disabled").length !== 2 ) { 1332 rbuggyQSA.push( ":enabled", ":disabled" ); 1333 } 1334 1335 // Opera 10-11 does not throw on post-comma invalid pseudos 1336 el.querySelectorAll("*,:x"); 1337 rbuggyQSA.push(",.*:"); 1338 }); 1339 } 1340 1341 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || 1342 docElem.webkitMatchesSelector || 1343 docElem.mozMatchesSelector || 1344 docElem.oMatchesSelector || 1345 docElem.msMatchesSelector) )) ) { 1346 1347 assert(function( el ) { 1348 // Check to see if it's possible to do matchesSelector 1349 // on a disconnected node (IE 9) 1350 support.disconnectedMatch = matches.call( el, "*" ); 1351 1352 // This should fail with an exception 1353 // Gecko does not error, returns false instead 1354 matches.call( el, "[s!='']:x" ); 1355 rbuggyMatches.push( "!=", pseudos ); 1356 }); 1357 } 1358 1359 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 1360 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 1361 1362 /* Contains 1363 ---------------------------------------------------------------------- */ 1364 hasCompare = rnative.test( docElem.compareDocumentPosition ); 1365 1366 // Element contains another 1367 // Purposefully self-exclusive 1368 // As in, an element does not contain itself 1369 contains = hasCompare || rnative.test( docElem.contains ) ? 1370 function( a, b ) { 1371 var adown = a.nodeType === 9 ? a.documentElement : a, 1372 bup = b && b.parentNode; 1373 return a === bup || !!( bup && bup.nodeType === 1 && ( 1374 adown.contains ? 1375 adown.contains( bup ) : 1376 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 1377 )); 1378 } : 1379 function( a, b ) { 1380 if ( b ) { 1381 while ( (b = b.parentNode) ) { 1382 if ( b === a ) { 1383 return true; 1384 } 1385 } 1386 } 1387 return false; 1388 }; 1389 1390 /* Sorting 1391 ---------------------------------------------------------------------- */ 1392 1393 // Document order sorting 1394 sortOrder = hasCompare ? 1395 function( a, b ) { 1396 1397 // Flag for duplicate removal 1398 if ( a === b ) { 1399 hasDuplicate = true; 1400 return 0; 1401 } 1402 1403 // Sort on method existence if only one input has compareDocumentPosition 1404 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1405 if ( compare ) { 1406 return compare; 1407 } 1408 1409 // Calculate position if both inputs belong to the same document 1410 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 1411 a.compareDocumentPosition( b ) : 1412 1413 // Otherwise we know they are disconnected 1414 1; 1415 1416 // Disconnected nodes 1417 if ( compare & 1 || 1418 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 1419 1420 // Choose the first element that is related to our preferred document 1421 if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 1422 return -1; 1423 } 1424 if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 1425 return 1; 1426 } 1427 1428 // Maintain original order 1429 return sortInput ? 1430 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1431 0; 1432 } 1433 1434 return compare & 4 ? -1 : 1; 1435 } : 1436 function( a, b ) { 1437 // Exit early if the nodes are identical 1438 if ( a === b ) { 1439 hasDuplicate = true; 1440 return 0; 1441 } 1442 1443 var cur, 1444 i = 0, 1445 aup = a.parentNode, 1446 bup = b.parentNode, 1447 ap = [ a ], 1448 bp = [ b ]; 1449 1450 // Parentless nodes are either documents or disconnected 1451 if ( !aup || !bup ) { 1452 return a === document ? -1 : 1453 b === document ? 1 : 1454 aup ? -1 : 1455 bup ? 1 : 1456 sortInput ? 1457 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1458 0; 1459 1460 // If the nodes are siblings, we can do a quick check 1461 } else if ( aup === bup ) { 1462 return siblingCheck( a, b ); 1463 } 1464 1465 // Otherwise we need full lists of their ancestors for comparison 1466 cur = a; 1467 while ( (cur = cur.parentNode) ) { 1468 ap.unshift( cur ); 1469 } 1470 cur = b; 1471 while ( (cur = cur.parentNode) ) { 1472 bp.unshift( cur ); 1473 } 1474 1475 // Walk down the tree looking for a discrepancy 1476 while ( ap[i] === bp[i] ) { 1477 i++; 1478 } 1479 1480 return i ? 1481 // Do a sibling check if the nodes have a common ancestor 1482 siblingCheck( ap[i], bp[i] ) : 1483 1484 // Otherwise nodes in our document sort first 1485 ap[i] === preferredDoc ? -1 : 1486 bp[i] === preferredDoc ? 1 : 1487 0; 1488 }; 1489 1490 return document; 1491}; 1492 1493Sizzle.matches = function( expr, elements ) { 1494 return Sizzle( expr, null, null, elements ); 1495}; 1496 1497Sizzle.matchesSelector = function( elem, expr ) { 1498 // Set document vars if needed 1499 if ( ( elem.ownerDocument || elem ) !== document ) { 1500 setDocument( elem ); 1501 } 1502 1503 if ( support.matchesSelector && documentIsHTML && 1504 !nonnativeSelectorCache[ expr + " " ] && 1505 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 1506 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 1507 1508 try { 1509 var ret = matches.call( elem, expr ); 1510 1511 // IE 9's matchesSelector returns false on disconnected nodes 1512 if ( ret || support.disconnectedMatch || 1513 // As well, disconnected nodes are said to be in a document 1514 // fragment in IE 9 1515 elem.document && elem.document.nodeType !== 11 ) { 1516 return ret; 1517 } 1518 } catch (e) { 1519 nonnativeSelectorCache( expr, true ); 1520
vendor: 12,942 bytes, lines 1520-1979
1520} 1521 } 1522 1523 return Sizzle( expr, document, null, [ elem ] ).length > 0; 1524}; 1525 1526Sizzle.contains = function( context, elem ) { 1527 // Set document vars if needed 1528 if ( ( context.ownerDocument || context ) !== document ) { 1529 setDocument( context ); 1530 } 1531 return contains( context, elem ); 1532}; 1533 1534Sizzle.attr = function( elem, name ) { 1535 // Set document vars if needed 1536 if ( ( elem.ownerDocument || elem ) !== document ) { 1537 setDocument( elem ); 1538 } 1539 1540 var fn = Expr.attrHandle[ name.toLowerCase() ], 1541 // Don't get fooled by Object.prototype properties (jQuery #13807) 1542 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 1543 fn( elem, name, !documentIsHTML ) : 1544 undefined; 1545 1546 return val !== undefined ? 1547 val : 1548 support.attributes || !documentIsHTML ? 1549 elem.getAttribute( name ) : 1550 (val = elem.getAttributeNode(name)) && val.specified ? 1551 val.value : 1552 null; 1553}; 1554 1555Sizzle.escape = function( sel ) { 1556 return (sel + "").replace( rcssescape, fcssescape ); 1557}; 1558 1559Sizzle.error = function( msg ) { 1560 throw new Error( "Syntax error, unrecognized expression: " + msg ); 1561}; 1562 1563/** 1564 * Document sorting and removing duplicates 1565 * @param {ArrayLike} results 1566 */ 1567Sizzle.uniqueSort = function( results ) { 1568 var elem, 1569 duplicates = [], 1570 j = 0, 1571 i = 0; 1572 1573 // Unless we *know* we can detect duplicates, assume their presence 1574 hasDuplicate = !support.detectDuplicates; 1575 sortInput = !support.sortStable && results.slice( 0 ); 1576 results.sort( sortOrder ); 1577 1578 if ( hasDuplicate ) { 1579 while ( (elem = results[i++]) ) { 1580 if ( elem === results[ i ] ) { 1581 j = duplicates.push( i ); 1582 } 1583 } 1584 while ( j-- ) { 1585 results.splice( duplicates[ j ], 1 ); 1586 } 1587 } 1588 1589 // Clear input after sorting to release objects 1590 // See https://github.com/jquery/sizzle/pull/225 1591 sortInput = null; 1592 1593 return results; 1594}; 1595 1596/** 1597 * Utility function for retrieving the text value of an array of DOM nodes 1598 * @param {Array|Element} elem 1599 */ 1600getText = Sizzle.getText = function( elem ) { 1601 var node, 1602 ret = "", 1603 i = 0, 1604 nodeType = elem.nodeType; 1605 1606 if ( !nodeType ) { 1607 // If no nodeType, this is expected to be an array 1608 while ( (node = elem[i++]) ) { 1609 // Do not traverse comment nodes 1610 ret += getText( node ); 1611 } 1612 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 1613 // Use textContent for elements 1614 // innerText usage removed for consistency of new lines (jQuery #11153) 1615 if ( typeof elem.textContent === "string" ) { 1616 return elem.textContent; 1617 } else { 1618 // Traverse its children 1619 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1620 ret += getText( elem ); 1621 } 1622 } 1623 } else if ( nodeType === 3 || nodeType === 4 ) { 1624 return elem.nodeValue; 1625 } 1626 // Do not include comment or processing instruction nodes 1627 1628 return ret; 1629}; 1630 1631Expr = Sizzle.selectors = { 1632 1633 // Can be adjusted by the user 1634 cacheLength: 50, 1635 1636 createPseudo: markFunction, 1637 1638 match: matchExpr, 1639 1640 attrHandle: {}, 1641 1642 find: {}, 1643 1644 relative: { 1645 ">": { dir: "parentNode", first: true }, 1646 " ": { dir: "parentNode" }, 1647 "+": { dir: "previousSibling", first: true }, 1648 "~": { dir: "previousSibling" } 1649 }, 1650 1651 preFilter: { 1652 "ATTR": function( match ) { 1653 match[1] = match[1].replace( runescape, funescape ); 1654 1655 // Move the given value to match[3] whether quoted or unquoted 1656 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); 1657 1658 if ( match[2] === "~=" ) { 1659 match[3] = " " + match[3] + " "; 1660 } 1661 1662 return match.slice( 0, 4 ); 1663 }, 1664 1665 "CHILD": function( match ) { 1666 /* matches from matchExpr["CHILD"] 1667 1 type (only|nth|...) 1668 2 what (child|of-type) 1669 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1670 4 xn-component of xn+y argument ([+-]?\d*n|) 1671 5 sign of xn-component 1672 6 x of xn-component 1673 7 sign of y-component 1674 8 y of y-component 1675 */ 1676 match[1] = match[1].toLowerCase(); 1677 1678 if ( match[1].slice( 0, 3 ) === "nth" ) { 1679 // nth-* requires argument 1680 if ( !match[3] ) { 1681 Sizzle.error( match[0] ); 1682 } 1683 1684 // numeric x and y parameters for Expr.filter.CHILD 1685 // remember that false/true cast respectively to 0/1 1686 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 1687 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 1688 1689 // other types prohibit arguments 1690 } else if ( match[3] ) { 1691 Sizzle.error( match[0] ); 1692 } 1693 1694 return match; 1695 }, 1696 1697 "PSEUDO": function( match ) { 1698 var excess, 1699 unquoted = !match[6] && match[2]; 1700 1701 if ( matchExpr["CHILD"].test( match[0] ) ) { 1702 return null; 1703 } 1704 1705 // Accept quoted arguments as-is 1706 if ( match[3] ) { 1707 match[2] = match[4] || match[5] || ""; 1708 1709 // Strip excess characters from unquoted arguments 1710 } else if ( unquoted && rpseudo.test( unquoted ) && 1711 // Get excess from tokenize (recursively) 1712 (excess = tokenize( unquoted, true )) && 1713 // advance to the next closing parenthesis 1714 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 1715 1716 // excess is a negative index 1717 match[0] = match[0].slice( 0, excess ); 1718 match[2] = unquoted.slice( 0, excess ); 1719 } 1720 1721 // Return only captures needed by the pseudo filter method (type and argument) 1722 return match.slice( 0, 3 ); 1723 } 1724 }, 1725 1726 filter: { 1727 1728 "TAG": function( nodeNameSelector ) { 1729 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 1730 return nodeNameSelector === "*" ? 1731 function() { return true; } : 1732 function( elem ) { 1733 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 1734 }; 1735 }, 1736 1737 "CLASS": function( className ) { 1738 var pattern = classCache[ className + " " ]; 1739 1740 return pattern || 1741 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 1742 classCache( className, function( elem ) { 1743 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); 1744 }); 1745 }, 1746 1747 "ATTR": function( name, operator, check ) { 1748 return function( elem ) { 1749 var result = Sizzle.attr( elem, name ); 1750 1751 if ( result == null ) { 1752 return operator === "!="; 1753 } 1754 if ( !operator ) { 1755 return true; 1756 } 1757 1758 result += ""; 1759 1760 return operator === "=" ? result === check : 1761 operator === "!=" ? result !== check : 1762 operator === "^=" ? check && result.indexOf( check ) === 0 : 1763 operator === "*=" ? check && result.indexOf( check ) > -1 : 1764 operator === "$=" ? check && result.slice( -check.length ) === check : 1765 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : 1766 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 1767 false; 1768 }; 1769 }, 1770 1771 "CHILD": function( type, what, argument, first, last ) { 1772 var simple = type.slice( 0, 3 ) !== "nth", 1773 forward = type.slice( -4 ) !== "last", 1774 ofType = what === "of-type"; 1775 1776 return first === 1 && last === 0 ? 1777 1778 // Shortcut for :nth-*(n) 1779 function( elem ) { 1780 return !!elem.parentNode; 1781 } : 1782 1783 function( elem, context, xml ) { 1784 var cache, uniqueCache, outerCache, node, nodeIndex, start, 1785 dir = simple !== forward ? "nextSibling" : "previousSibling", 1786 parent = elem.parentNode, 1787 name = ofType && elem.nodeName.toLowerCase(), 1788 useCache = !xml && !ofType, 1789 diff = false; 1790 1791 if ( parent ) { 1792 1793 // :(first|last|only)-(child|of-type) 1794 if ( simple ) { 1795 while ( dir ) { 1796 node = elem; 1797 while ( (node = node[ dir ]) ) { 1798 if ( ofType ? 1799 node.nodeName.toLowerCase() === name : 1800 node.nodeType === 1 ) { 1801 1802 return false; 1803 } 1804 } 1805 // Reverse direction for :only-* (if we haven't yet done so) 1806 start = dir = type === "only" && !start && "nextSibling"; 1807 } 1808 return true; 1809 } 1810 1811 start = [ forward ? parent.firstChild : parent.lastChild ]; 1812 1813 // non-xml :nth-child(...) stores cache data on `parent` 1814 if ( forward && useCache ) { 1815 1816 // Seek `elem` from a previously-cached index 1817 1818 // ...in a gzip-friendly way 1819 node = parent; 1820 outerCache = node[ expando ] || (node[ expando ] = {}); 1821 1822 // Support: IE <9 only 1823 // Defend against cloned attroperties (jQuery gh-1709) 1824 uniqueCache = outerCache[ node.uniqueID ] || 1825 (outerCache[ node.uniqueID ] = {}); 1826 1827 cache = uniqueCache[ type ] || []; 1828 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1829 diff = nodeIndex && cache[ 2 ]; 1830 node = nodeIndex && parent.childNodes[ nodeIndex ]; 1831 1832 while ( (node = ++nodeIndex && node && node[ dir ] || 1833 1834 // Fallback to seeking `elem` from the start 1835 (diff = nodeIndex = 0) || start.pop()) ) { 1836 1837 // When found, cache indexes on `parent` and break 1838 if ( node.nodeType === 1 && ++diff && node === elem ) { 1839 uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; 1840 break; 1841 } 1842 } 1843 1844 } else { 1845 // Use previously-cached element index if available 1846 if ( useCache ) { 1847 // ...in a gzip-friendly way 1848 node = elem; 1849 outerCache = node[ expando ] || (node[ expando ] = {}); 1850 1851 // Support: IE <9 only 1852 // Defend against cloned attroperties (jQuery gh-1709) 1853 uniqueCache = outerCache[ node.uniqueID ] || 1854 (outerCache[ node.uniqueID ] = {}); 1855 1856 cache = uniqueCache[ type ] || []; 1857 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1858 diff = nodeIndex; 1859 } 1860 1861 // xml :nth-child(...) 1862 // or :nth-last-child(...) or :nth(-last)?-of-type(...) 1863 if ( diff === false ) { 1864 // Use the same loop as above to seek `elem` from the start 1865 while ( (node = ++nodeIndex && node && node[ dir ] || 1866 (diff = nodeIndex = 0) || start.pop()) ) { 1867 1868 if ( ( ofType ? 1869 node.nodeName.toLowerCase() === name : 1870 node.nodeType === 1 ) && 1871 ++diff ) { 1872 1873 // Cache the index of each encountered element 1874 if ( useCache ) { 1875 outerCache = node[ expando ] || (node[ expando ] = {}); 1876 1877 // Support: IE <9 only 1878 // Defend against cloned attroperties (jQuery gh-1709) 1879 uniqueCache = outerCache[ node.uniqueID ] || 1880 (outerCache[ node.uniqueID ] = {}); 1881 1882 uniqueCache[ type ] = [ dirruns, diff ]; 1883 } 1884 1885 if ( node === elem ) { 1886 break; 1887 } 1888 } 1889 } 1890 } 1891 } 1892 1893 // Incorporate the offset, then check against cycle size 1894 diff -= last; 1895 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 1896 } 1897 }; 1898 }, 1899 1900 "PSEUDO": function( pseudo, argument ) { 1901 // pseudo-class names are case-insensitive 1902 // http://www.w3.org/TR/selectors/#pseudo-classes 1903 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1904 // Remember that setFilters inherits from pseudos 1905 var args, 1906 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 1907 Sizzle.error( "unsupported pseudo: " + pseudo ); 1908 1909 // The user may use createPseudo to indicate that 1910 // arguments are needed to create the filter function 1911 // just as Sizzle does 1912 if ( fn[ expando ] ) { 1913 return fn( argument ); 1914 } 1915 1916 // But maintain support for old signatures 1917 if ( fn.length > 1 ) { 1918 args = [ pseudo, pseudo, "", argument ]; 1919 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 1920 markFunction(function( seed, matches ) { 1921 var idx, 1922 matched = fn( seed, argument ), 1923 i = matched.length; 1924 while ( i-- ) { 1925 idx = indexOf( seed, matched[i] ); 1926 seed[ idx ] = !( matches[ idx ] = matched[i] ); 1927 } 1928 }) : 1929 function( elem ) { 1930 return fn( elem, 0, args ); 1931 }; 1932 } 1933 1934 return fn; 1935 } 1936 }, 1937 1938 pseudos: { 1939 // Potentially complex pseudos 1940 "not": markFunction(function( selector ) { 1941 // Trim the selector passed to compile 1942 // to avoid treating leading and trailing 1943 // spaces as combinators 1944 var input = [], 1945 results = [], 1946 matcher = compile( selector.replace( rtrim, "$1" ) ); 1947 1948 return matcher[ expando ] ? 1949 markFunction(function( seed, matches, context, xml ) { 1950 var elem, 1951 unmatched = matcher( seed, null, xml, [] ), 1952 i = seed.length; 1953 1954 // Match elements unmatched by `matcher` 1955 while ( i-- ) { 1956 if ( (elem = unmatched[i]) ) { 1957 seed[i] = !(matches[i] = elem); 1958 } 1959 } 1960 }) : 1961 function( elem, context, xml ) { 1962 input[0] = elem; 1963 matcher( input, null, xml, results ); 1964 // Don't keep the element (issue #299) 1965 input[0] = null; 1966 return !results.pop(); 1967 }; 1968 }), 1969 1970 "has": markFunction(function( selector ) { 1971 return function( elem ) { 1972 return Sizzle( selector, elem ).length > 0; 1973 }; 1974 }), 1975 1976 "contains": markFunction(function( text ) { 1977 text = text.replace( runescape, funescape ); 1978 return function( elem ) { 1979 return ( elem.textContent ||
vendor: 25,129 bytes, lines 1979-2883
1979getText( elem ) ).indexOf( text ) > -1; 1980 }; 1981 }), 1982 1983 // "Whether an element is represented by a :lang() selector 1984 // is based solely on the element's language value 1985 // being equal to the identifier C, 1986 // or beginning with the identifier C immediately followed by "-". 1987 // The matching of C against the element's language value is performed case-insensitively. 1988 // The identifier C does not have to be a valid language name." 1989 // http://www.w3.org/TR/selectors/#lang-pseudo 1990 "lang": markFunction( function( lang ) { 1991 // lang value must be a valid identifier 1992 if ( !ridentifier.test(lang || "") ) { 1993 Sizzle.error( "unsupported lang: " + lang ); 1994 } 1995 lang = lang.replace( runescape, funescape ).toLowerCase(); 1996 return function( elem ) { 1997 var elemLang; 1998 do { 1999 if ( (elemLang = documentIsHTML ? 2000 elem.lang : 2001 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 2002 2003 elemLang = elemLang.toLowerCase(); 2004 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 2005 } 2006 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 2007 return false; 2008 }; 2009 }), 2010 2011 // Miscellaneous 2012 "target": function( elem ) { 2013 var hash = window.location && window.location.hash; 2014 return hash && hash.slice( 1 ) === elem.id; 2015 }, 2016 2017 "root": function( elem ) { 2018 return elem === docElem; 2019 }, 2020 2021 "focus": function( elem ) { 2022 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 2023 }, 2024 2025 // Boolean properties 2026 "enabled": createDisabledPseudo( false ), 2027 "disabled": createDisabledPseudo( true ), 2028 2029 "checked": function( elem ) { 2030 // In CSS3, :checked should return both checked and selected elements 2031 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 2032 var nodeName = elem.nodeName.toLowerCase(); 2033 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 2034 }, 2035 2036 "selected": function( elem ) { 2037 // Accessing this property makes selected-by-default 2038 // options in Safari work properly 2039 if ( elem.parentNode ) { 2040 elem.parentNode.selectedIndex; 2041 } 2042 2043 return elem.selected === true; 2044 }, 2045 2046 // Contents 2047 "empty": function( elem ) { 2048 // http://www.w3.org/TR/selectors/#empty-pseudo 2049 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 2050 // but not by others (comment: 8; processing instruction: 7; etc.) 2051 // nodeType < 6 works because attributes (2) do not appear as children 2052 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 2053 if ( elem.nodeType < 6 ) { 2054 return false; 2055 } 2056 } 2057 return true; 2058 }, 2059 2060 "parent": function( elem ) { 2061 return !Expr.pseudos["empty"]( elem ); 2062 }, 2063 2064 // Element/input types 2065 "header": function( elem ) { 2066 return rheader.test( elem.nodeName ); 2067 }, 2068 2069 "input": function( elem ) { 2070 return rinputs.test( elem.nodeName ); 2071 }, 2072 2073 "button": function( elem ) { 2074 var name = elem.nodeName.toLowerCase(); 2075 return name === "input" && elem.type === "button" || name === "button"; 2076 }, 2077 2078 "text": function( elem ) { 2079 var attr; 2080 return elem.nodeName.toLowerCase() === "input" && 2081 elem.type === "text" && 2082 2083 // Support: IE<8 2084 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 2085 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 2086 }, 2087 2088 // Position-in-collection 2089 "first": createPositionalPseudo(function() { 2090 return [ 0 ]; 2091 }), 2092 2093 "last": createPositionalPseudo(function( matchIndexes, length ) { 2094 return [ length - 1 ]; 2095 }), 2096 2097 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 2098 return [ argument < 0 ? argument + length : argument ]; 2099 }), 2100 2101 "even": createPositionalPseudo(function( matchIndexes, length ) { 2102 var i = 0; 2103 for ( ; i < length; i += 2 ) { 2104 matchIndexes.push( i ); 2105 } 2106 return matchIndexes; 2107 }), 2108 2109 "odd": createPositionalPseudo(function( matchIndexes, length ) { 2110 var i = 1; 2111 for ( ; i < length; i += 2 ) { 2112 matchIndexes.push( i ); 2113 } 2114 return matchIndexes; 2115 }), 2116 2117 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2118 var i = argument < 0 ? 2119 argument + length : 2120 argument > length ? 2121 length : 2122 argument; 2123 for ( ; --i >= 0; ) { 2124 matchIndexes.push( i ); 2125 } 2126 return matchIndexes; 2127 }), 2128 2129 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2130 var i = argument < 0 ? argument + length : argument; 2131 for ( ; ++i < length; ) { 2132 matchIndexes.push( i ); 2133 } 2134 return matchIndexes; 2135 }) 2136 } 2137}; 2138 2139Expr.pseudos["nth"] = Expr.pseudos["eq"]; 2140 2141// Add button/input type pseudos 2142for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 2143 Expr.pseudos[ i ] = createInputPseudo( i ); 2144} 2145for ( i in { submit: true, reset: true } ) { 2146 Expr.pseudos[ i ] = createButtonPseudo( i ); 2147} 2148 2149// Easy API for creating new setFilters 2150function setFilters() {} 2151setFilters.prototype = Expr.filters = Expr.pseudos; 2152Expr.setFilters = new setFilters(); 2153 2154tokenize = Sizzle.tokenize = function( selector, parseOnly ) { 2155 var matched, match, tokens, type, 2156 soFar, groups, preFilters, 2157 cached = tokenCache[ selector + " " ]; 2158 2159 if ( cached ) { 2160 return parseOnly ? 0 : cached.slice( 0 ); 2161 } 2162 2163 soFar = selector; 2164 groups = []; 2165 preFilters = Expr.preFilter; 2166 2167 while ( soFar ) { 2168 2169 // Comma and first run 2170 if ( !matched || (match = rcomma.exec( soFar )) ) { 2171 if ( match ) { 2172 // Don't consume trailing commas as valid 2173 soFar = soFar.slice( match[0].length ) || soFar; 2174 } 2175 groups.push( (tokens = []) ); 2176 } 2177 2178 matched = false; 2179 2180 // Combinators 2181 if ( (match = rcombinators.exec( soFar )) ) { 2182 matched = match.shift(); 2183 tokens.push({ 2184 value: matched, 2185 // Cast descendant combinators to space 2186 type: match[0].replace( rtrim, " " ) 2187 }); 2188 soFar = soFar.slice( matched.length ); 2189 } 2190 2191 // Filters 2192 for ( type in Expr.filter ) { 2193 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 2194 (match = preFilters[ type ]( match ))) ) { 2195 matched = match.shift(); 2196 tokens.push({ 2197 value: matched, 2198 type: type, 2199 matches: match 2200 }); 2201 soFar = soFar.slice( matched.length ); 2202 } 2203 } 2204 2205 if ( !matched ) { 2206 break; 2207 } 2208 } 2209 2210 // Return the length of the invalid excess 2211 // if we're just parsing 2212 // Otherwise, throw an error or return tokens 2213 return parseOnly ? 2214 soFar.length : 2215 soFar ? 2216 Sizzle.error( selector ) : 2217 // Cache the tokens 2218 tokenCache( selector, groups ).slice( 0 ); 2219}; 2220 2221function toSelector( tokens ) { 2222 var i = 0, 2223 len = tokens.length, 2224 selector = ""; 2225 for ( ; i < len; i++ ) { 2226 selector += tokens[i].value; 2227 } 2228 return selector; 2229} 2230 2231function addCombinator( matcher, combinator, base ) { 2232 var dir = combinator.dir, 2233 skip = combinator.next, 2234 key = skip || dir, 2235 checkNonElements = base && key === "parentNode", 2236 doneName = done++; 2237 2238 return combinator.first ? 2239 // Check against closest ancestor/preceding element 2240 function( elem, context, xml ) { 2241 while ( (elem = elem[ dir ]) ) { 2242 if ( elem.nodeType === 1 || checkNonElements ) { 2243 return matcher( elem, context, xml ); 2244 } 2245 } 2246 return false; 2247 } : 2248 2249 // Check against all ancestor/preceding elements 2250 function( elem, context, xml ) { 2251 var oldCache, uniqueCache, outerCache, 2252 newCache = [ dirruns, doneName ]; 2253 2254 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching 2255 if ( xml ) { 2256 while ( (elem = elem[ dir ]) ) { 2257 if ( elem.nodeType === 1 || checkNonElements ) { 2258 if ( matcher( elem, context, xml ) ) { 2259 return true; 2260 } 2261 } 2262 } 2263 } else { 2264 while ( (elem = elem[ dir ]) ) { 2265 if ( elem.nodeType === 1 || checkNonElements ) { 2266 outerCache = elem[ expando ] || (elem[ expando ] = {}); 2267 2268 // Support: IE <9 only 2269 // Defend against cloned attroperties (jQuery gh-1709) 2270 uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); 2271 2272 if ( skip && skip === elem.nodeName.toLowerCase() ) { 2273 elem = elem[ dir ] || elem; 2274 } else if ( (oldCache = uniqueCache[ key ]) && 2275 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 2276 2277 // Assign to newCache so results back-propagate to previous elements 2278 return (newCache[ 2 ] = oldCache[ 2 ]); 2279 } else { 2280 // Reuse newcache so results back-propagate to previous elements 2281 uniqueCache[ key ] = newCache; 2282 2283 // A match means we're done; a fail means we have to keep checking 2284 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 2285 return true; 2286 } 2287 } 2288 } 2289 } 2290 } 2291 return false; 2292 }; 2293} 2294 2295function elementMatcher( matchers ) { 2296 return matchers.length > 1 ? 2297 function( elem, context, xml ) { 2298 var i = matchers.length; 2299 while ( i-- ) { 2300 if ( !matchers[i]( elem, context, xml ) ) { 2301 return false; 2302 } 2303 } 2304 return true; 2305 } : 2306 matchers[0]; 2307} 2308 2309function multipleContexts( selector, contexts, results ) { 2310 var i = 0, 2311 len = contexts.length; 2312 for ( ; i < len; i++ ) { 2313 Sizzle( selector, contexts[i], results ); 2314 } 2315 return results; 2316} 2317 2318function condense( unmatched, map, filter, context, xml ) { 2319 var elem, 2320 newUnmatched = [], 2321 i = 0, 2322 len = unmatched.length, 2323 mapped = map != null; 2324 2325 for ( ; i < len; i++ ) { 2326 if ( (elem = unmatched[i]) ) { 2327 if ( !filter || filter( elem, context, xml ) ) { 2328 newUnmatched.push( elem ); 2329 if ( mapped ) { 2330 map.push( i ); 2331 } 2332 } 2333 } 2334 } 2335 2336 return newUnmatched; 2337} 2338 2339function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 2340 if ( postFilter && !postFilter[ expando ] ) { 2341 postFilter = setMatcher( postFilter ); 2342 } 2343 if ( postFinder && !postFinder[ expando ] ) { 2344 postFinder = setMatcher( postFinder, postSelector ); 2345 } 2346 return markFunction(function( seed, results, context, xml ) { 2347 var temp, i, elem, 2348 preMap = [], 2349 postMap = [], 2350 preexisting = results.length, 2351 2352 // Get initial elements from seed or context 2353 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 2354 2355 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2356 matcherIn = preFilter && ( seed || !selector ) ? 2357 condense( elems, preMap, preFilter, context, xml ) : 2358 elems, 2359 2360 matcherOut = matcher ? 2361 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 2362 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 2363 2364 // ...intermediate processing is necessary 2365 [] : 2366 2367 // ...otherwise use results directly 2368 results : 2369 matcherIn; 2370 2371 // Find primary matches 2372 if ( matcher ) { 2373 matcher( matcherIn, matcherOut, context, xml ); 2374 } 2375 2376 // Apply postFilter 2377 if ( postFilter ) { 2378 temp = condense( matcherOut, postMap ); 2379 postFilter( temp, [], context, xml ); 2380 2381 // Un-match failing elements by moving them back to matcherIn 2382 i = temp.length; 2383 while ( i-- ) { 2384 if ( (elem = temp[i]) ) { 2385 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 2386 } 2387 } 2388 } 2389 2390 if ( seed ) { 2391 if ( postFinder || preFilter ) { 2392 if ( postFinder ) { 2393 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2394 temp = []; 2395 i = matcherOut.length; 2396 while ( i-- ) { 2397 if ( (elem = matcherOut[i]) ) { 2398 // Restore matcherIn since elem is not yet a final match 2399 temp.push( (matcherIn[i] = elem) ); 2400 } 2401 } 2402 postFinder( null, (matcherOut = []), temp, xml ); 2403 } 2404 2405 // Move matched elements from seed to results to keep them synchronized 2406 i = matcherOut.length; 2407 while ( i-- ) { 2408 if ( (elem = matcherOut[i]) && 2409 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { 2410 2411 seed[temp] = !(results[temp] = elem); 2412 } 2413 } 2414 } 2415 2416 // Add elements to results, through postFinder if defined 2417 } else { 2418 matcherOut = condense( 2419 matcherOut === results ? 2420 matcherOut.splice( preexisting, matcherOut.length ) : 2421 matcherOut 2422 ); 2423 if ( postFinder ) { 2424 postFinder( null, results, matcherOut, xml ); 2425 } else { 2426 push.apply( results, matcherOut ); 2427 } 2428 } 2429 }); 2430} 2431 2432function matcherFromTokens( tokens ) { 2433 var checkContext, matcher, j, 2434 len = tokens.length, 2435 leadingRelative = Expr.relative[ tokens[0].type ], 2436 implicitRelative = leadingRelative || Expr.relative[" "], 2437 i = leadingRelative ? 1 : 0, 2438 2439 // The foundational matcher ensures that elements are reachable from top-level context(s) 2440 matchContext = addCombinator( function( elem ) { 2441 return elem === checkContext; 2442 }, implicitRelative, true ), 2443 matchAnyContext = addCombinator( function( elem ) { 2444 return indexOf( checkContext, elem ) > -1; 2445 }, implicitRelative, true ), 2446 matchers = [ function( elem, context, xml ) { 2447 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 2448 (checkContext = context).nodeType ? 2449 matchContext( elem, context, xml ) : 2450 matchAnyContext( elem, context, xml ) ); 2451 // Avoid hanging onto element (issue #299) 2452 checkContext = null; 2453 return ret; 2454 } ]; 2455 2456 for ( ; i < len; i++ ) { 2457 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 2458 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 2459 } else { 2460 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 2461 2462 // Return special upon seeing a positional matcher 2463 if ( matcher[ expando ] ) { 2464 // Find the next relative operator (if any) for proper handling 2465 j = ++i; 2466 for ( ; j < len; j++ ) { 2467 if ( Expr.relative[ tokens[j].type ] ) { 2468 break; 2469 } 2470 } 2471 return setMatcher( 2472 i > 1 && elementMatcher( matchers ), 2473 i > 1 && toSelector( 2474 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2475 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 2476 ).replace( rtrim, "$1" ), 2477 matcher, 2478 i < j && matcherFromTokens( tokens.slice( i, j ) ), 2479 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 2480 j < len && toSelector( tokens ) 2481 ); 2482 } 2483 matchers.push( matcher ); 2484 } 2485 } 2486 2487 return elementMatcher( matchers ); 2488} 2489 2490function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 2491 var bySet = setMatchers.length > 0, 2492 byElement = elementMatchers.length > 0, 2493 superMatcher = function( seed, context, xml, results, outermost ) { 2494 var elem, j, matcher, 2495 matchedCount = 0, 2496 i = "0", 2497 unmatched = seed && [], 2498 setMatched = [], 2499 contextBackup = outermostContext, 2500 // We must always have either seed elements or outermost context 2501 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 2502 // Use integer dirruns iff this is the outermost matcher 2503 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 2504 len = elems.length; 2505 2506 if ( outermost ) { 2507 outermostContext = context === document || context || outermost; 2508 } 2509 2510 // Add elements passing elementMatchers directly to results 2511 // Support: IE<9, Safari 2512 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 2513 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 2514 if ( byElement && elem ) { 2515 j = 0; 2516 if ( !context && elem.ownerDocument !== document ) { 2517 setDocument( elem ); 2518 xml = !documentIsHTML; 2519 } 2520 while ( (matcher = elementMatchers[j++]) ) { 2521 if ( matcher( elem, context || document, xml) ) { 2522 results.push( elem ); 2523 break; 2524 } 2525 } 2526 if ( outermost ) { 2527 dirruns = dirrunsUnique; 2528 } 2529 } 2530 2531 // Track unmatched elements for set filters 2532 if ( bySet ) { 2533 // They will have gone through all possible matchers 2534 if ( (elem = !matcher && elem) ) { 2535 matchedCount--; 2536 } 2537 2538 // Lengthen the array for every element, matched or not 2539 if ( seed ) { 2540 unmatched.push( elem ); 2541 } 2542 } 2543 } 2544 2545 // `i` is now the count of elements visited above, and adding it to `matchedCount` 2546 // makes the latter nonnegative. 2547 matchedCount += i; 2548 2549 // Apply set filters to unmatched elements 2550 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` 2551 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have 2552 // no element matchers and no seed. 2553 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that 2554 // case, which will result in a "00" `matchedCount` that differs from `i` but is also 2555 // numerically zero. 2556 if ( bySet && i !== matchedCount ) { 2557 j = 0; 2558 while ( (matcher = setMatchers[j++]) ) { 2559 matcher( unmatched, setMatched, context, xml ); 2560 } 2561 2562 if ( seed ) { 2563 // Reintegrate element matches to eliminate the need for sorting 2564 if ( matchedCount > 0 ) { 2565 while ( i-- ) { 2566 if ( !(unmatched[i] || setMatched[i]) ) { 2567 setMatched[i] = pop.call( results ); 2568 } 2569 } 2570 } 2571 2572 // Discard index placeholder values to get only actual matches 2573 setMatched = condense( setMatched ); 2574 } 2575 2576 // Add matches to results 2577 push.apply( results, setMatched ); 2578 2579 // Seedless set matches succeeding multiple successful matchers stipulate sorting 2580 if ( outermost && !seed && setMatched.length > 0 && 2581 ( matchedCount + setMatchers.length ) > 1 ) { 2582 2583 Sizzle.uniqueSort( results ); 2584 } 2585 } 2586 2587 // Override manipulation of globals by nested matchers 2588 if ( outermost ) { 2589 dirruns = dirrunsUnique; 2590 outermostContext = contextBackup; 2591 } 2592 2593 return unmatched; 2594 }; 2595 2596 return bySet ? 2597 markFunction( superMatcher ) : 2598 superMatcher; 2599} 2600 2601compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { 2602 var i, 2603 setMatchers = [], 2604 elementMatchers = [], 2605 cached = compilerCache[ selector + " " ]; 2606 2607 if ( !cached ) { 2608 // Generate a function of recursive functions that can be used to check each element 2609 if ( !match ) { 2610 match = tokenize( selector ); 2611 } 2612 i = match.length; 2613 while ( i-- ) { 2614 cached = matcherFromTokens( match[i] ); 2615 if ( cached[ expando ] ) { 2616 setMatchers.push( cached ); 2617 } else { 2618 elementMatchers.push( cached ); 2619 } 2620 } 2621 2622 // Cache the compiled function 2623 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 2624 2625 // Save selector and tokenization 2626 cached.selector = selector; 2627 } 2628 return cached; 2629}; 2630 2631/** 2632 * A low-level selection function that works with Sizzle's compiled 2633 * selector functions 2634 * @param {String|Function} selector A selector or a pre-compiled 2635 * selector function built with Sizzle.compile 2636 * @param {Element} context 2637 * @param {Array} [results] 2638 * @param {Array} [seed] A set of elements to match against 2639 */ 2640select = Sizzle.select = function( selector, context, results, seed ) { 2641 var i, tokens, token, type, find, 2642 compiled = typeof selector === "function" && selector, 2643 match = !seed && tokenize( (selector = compiled.selector || selector) ); 2644 2645 results = results || []; 2646 2647 // Try to minimize operations if there is only one selector in the list and no seed 2648 // (the latter of which guarantees us context) 2649 if ( match.length === 1 ) { 2650 2651 // Reduce context if the leading compound selector is an ID 2652 tokens = match[0] = match[0].slice( 0 ); 2653 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 2654 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { 2655 2656 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 2657 if ( !context ) { 2658 return results; 2659 2660 // Precompiled matchers will still verify ancestry, so step up a level 2661 } else if ( compiled ) { 2662 context = context.parentNode; 2663 } 2664 2665 selector = selector.slice( tokens.shift().value.length ); 2666 } 2667 2668 // Fetch a seed set for right-to-left matching 2669 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 2670 while ( i-- ) { 2671 token = tokens[i]; 2672 2673 // Abort if we hit a combinator 2674 if ( Expr.relative[ (type = token.type) ] ) { 2675 break; 2676 } 2677 if ( (find = Expr.find[ type ]) ) { 2678 // Search, expanding context for leading sibling combinators 2679 if ( (seed = find( 2680 token.matches[0].replace( runescape, funescape ), 2681 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 2682 )) ) { 2683 2684 // If seed is empty or no tokens remain, we can return early 2685 tokens.splice( i, 1 ); 2686 selector = seed.length && toSelector( tokens ); 2687 if ( !selector ) { 2688 push.apply( results, seed ); 2689 return results; 2690 } 2691 2692 break; 2693 } 2694 } 2695 } 2696 } 2697 2698 // Compile and execute a filtering function if one is not provided 2699 // Provide `match` to avoid retokenization if we modified the selector above 2700 ( compiled || compile( selector, match ) )( 2701 seed, 2702 context, 2703 !documentIsHTML, 2704 results, 2705 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context 2706 ); 2707 return results; 2708}; 2709 2710// One-time assignments 2711 2712// Sort stability 2713support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 2714 2715// Support: Chrome 14-35+ 2716// Always assume duplicates if they aren't passed to the comparison function 2717support.detectDuplicates = !!hasDuplicate; 2718 2719// Initialize against the default document 2720setDocument(); 2721 2722// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) 2723// Detached nodes confoundingly follow *each other* 2724support.sortDetached = assert(function( el ) { 2725 // Should return 1, but returns 4 (following) 2726 return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; 2727}); 2728 2729// Support: IE<8 2730// Prevent attribute/property "interpolation" 2731// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 2732if ( !assert(function( el ) { 2733 el.innerHTML = "<a href='#'></a>"; 2734 return el.firstChild.getAttribute("href") === "#" ; 2735}) ) { 2736 addHandle( "type|href|height|width", function( elem, name, isXML ) { 2737 if ( !isXML ) { 2738 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 2739 } 2740 }); 2741} 2742 2743// Support: IE<9 2744// Use defaultValue in place of getAttribute("value") 2745if ( !support.attributes || !assert(function( el ) { 2746 el.innerHTML = "<input/>"; 2747 el.firstChild.setAttribute( "value", "" ); 2748 return el.firstChild.getAttribute( "value" ) === ""; 2749}) ) { 2750 addHandle( "value", function( elem, name, isXML ) { 2751 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 2752 return elem.defaultValue; 2753 } 2754 }); 2755} 2756 2757// Support: IE<9 2758// Use getAttributeNode to fetch booleans when getAttribute lies 2759if ( !assert(function( el ) { 2760 return el.getAttribute("disabled") == null; 2761}) ) { 2762 addHandle( booleans, function( elem, name, isXML ) { 2763 var val; 2764 if ( !isXML ) { 2765 return elem[ name ] === true ? name.toLowerCase() : 2766 (val = elem.getAttributeNode( name )) && val.specified ? 2767 val.value : 2768 null; 2769 } 2770 }); 2771} 2772 2773return Sizzle; 2774 2775})( window ); 2776 2777 2778 2779jQuery.find = Sizzle; 2780jQuery.expr = Sizzle.selectors; 2781 2782// Deprecated 2783jQuery.expr[ ":" ] = jQuery.expr.pseudos; 2784jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; 2785jQuery.text = Sizzle.getText; 2786jQuery.isXMLDoc = Sizzle.isXML; 2787jQuery.contains = Sizzle.contains; 2788jQuery.escapeSelector = Sizzle.escape; 2789 2790 2791 2792 2793var dir = function( elem, dir, until ) { 2794 var matched = [], 2795 truncate = until !== undefined; 2796 2797 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { 2798 if ( elem.nodeType === 1 ) { 2799 if ( truncate && jQuery( elem ).is( until ) ) { 2800 break; 2801 } 2802 matched.push( elem ); 2803 } 2804 } 2805 return matched; 2806}; 2807 2808 2809var siblings = function( n, elem ) { 2810 var matched = []; 2811 2812 for ( ; n; n = n.nextSibling ) { 2813 if ( n.nodeType === 1 && n !== elem ) { 2814 matched.push( n ); 2815 } 2816 } 2817 2818 return matched; 2819}; 2820 2821 2822var rneedsContext = jQuery.expr.match.needsContext; 2823 2824 2825 2826function nodeName( elem, name ) { 2827 2828 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 2829 2830}; 2831var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); 2832 2833 2834 2835// Implement the identical functionality for filter and not 2836function winnow( elements, qualifier, not ) { 2837 if ( isFunction( qualifier ) ) { 2838 return jQuery.grep( elements, function( elem, i ) { 2839 return !!qualifier.call( elem, i, elem ) !== not; 2840 } ); 2841 } 2842 2843 // Single element 2844 if ( qualifier.nodeType ) { 2845 return jQuery.grep( elements, function( elem ) { 2846 return ( elem === qualifier ) !== not; 2847 } ); 2848 } 2849 2850 // Arraylike of elements (jQuery, arguments, Array) 2851 if ( typeof qualifier !== "string" ) { 2852 return jQuery.grep( elements, function( elem ) { 2853 return ( indexOf.call( qualifier, elem ) > -1 ) !== not; 2854 } ); 2855 } 2856 2857 // Filtered directly for both simple and complex selectors 2858 return jQuery.filter( qualifier, elements, not ); 2859} 2860 2861jQuery.filter = function( expr, elems, not ) { 2862 var elem = elems[ 0 ]; 2863 2864 if ( not ) { 2865 expr = ":not(" + expr + ")"; 2866 } 2867 2868 if ( elems.length === 1 && elem.nodeType === 1 ) { 2869 return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; 2870 } 2871 2872 return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 2873 return elem.nodeType === 1; 2874 } ) ); 2875}; 2876 2877jQuery.fn.extend( { 2878 find: function( selector ) { 2879 var i, ret, 2880 len = this.length, 2881 self = this; 2882 2883 if ( typeof selector !== "string" ) {
vendor: 4,662 bytes, lines 2884-3069
2884 return this.pushStack( jQuery( selector ).filter( function() { 2885 for ( i = 0; i < len; i++ ) { 2886 if ( jQuery.contains( self[ i ], this ) ) { 2887 return true; 2888 } 2889 } 2890 } ) ); 2891 } 2892 2893 ret = this.pushStack( [] ); 2894 2895 for ( i = 0; i < len; i++ ) { 2896 jQuery.find( selector, self[ i ], ret ); 2897 } 2898 2899 return len > 1 ? jQuery.uniqueSort( ret ) : ret; 2900 }, 2901 filter: function( selector ) { 2902 return this.pushStack( winnow( this, selector || [], false ) ); 2903 }, 2904 not: function( selector ) { 2905 return this.pushStack( winnow( this, selector || [], true ) ); 2906 }, 2907 is: function( selector ) { 2908 return !!winnow( 2909 this, 2910 2911 // If this is a positional/relative selector, check membership in the returned set 2912 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2913 typeof selector === "string" && rneedsContext.test( selector ) ? 2914 jQuery( selector ) : 2915 selector || [], 2916 false 2917 ).length; 2918 } 2919} ); 2920 2921 2922// Initialize a jQuery object 2923 2924 2925// A central reference to the root jQuery(document) 2926var rootjQuery, 2927 2928 // A simple way to check for HTML strings 2929 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 2930 // Strict HTML recognition (#11290: must start with <) 2931 // Shortcut simple #id case for speed 2932 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, 2933 2934 init = jQuery.fn.init = function( selector, context, root ) { 2935 var match, elem; 2936 2937 // HANDLE: $(""), $(null), $(undefined), $(false) 2938 if ( !selector ) { 2939 return this; 2940 } 2941 2942 // Method init() accepts an alternate rootjQuery 2943 // so migrate can support jQuery.sub (gh-2101) 2944 root = root || rootjQuery; 2945 2946 // Handle HTML strings 2947 if ( typeof selector === "string" ) { 2948 if ( selector[ 0 ] === "<" && 2949 selector[ selector.length - 1 ] === ">" && 2950 selector.length >= 3 ) { 2951 2952 // Assume that strings that start and end with <> are HTML and skip the regex check 2953 match = [ null, selector, null ]; 2954 2955 } else { 2956 match = rquickExpr.exec( selector ); 2957 } 2958 2959 // Match html or make sure no context is specified for #id 2960 if ( match && ( match[ 1 ] || !context ) ) { 2961 2962 // HANDLE: $(html) -> $(array) 2963 if ( match[ 1 ] ) { 2964 context = context instanceof jQuery ? context[ 0 ] : context; 2965 2966 // Option to run scripts is true for back-compat 2967 // Intentionally let the error be thrown if parseHTML is not present 2968 jQuery.merge( this, jQuery.parseHTML( 2969 match[ 1 ], 2970 context && context.nodeType ? context.ownerDocument || context : document, 2971 true 2972 ) ); 2973 2974 // HANDLE: $(html, props) 2975 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { 2976 for ( match in context ) { 2977 2978 // Properties of context are called as methods if possible 2979 if ( isFunction( this[ match ] ) ) { 2980 this[ match ]( context[ match ] ); 2981 2982 // ...and otherwise set as attributes 2983 } else { 2984 this.attr( match, context[ match ] ); 2985 } 2986 } 2987 } 2988 2989 return this; 2990 2991 // HANDLE: $(#id) 2992 } else { 2993 elem = document.getElementById( match[ 2 ] ); 2994 2995 if ( elem ) { 2996 2997 // Inject the element directly into the jQuery object 2998 this[ 0 ] = elem; 2999 this.length = 1; 3000 } 3001 return this; 3002 } 3003 3004 // HANDLE: $(expr, $(...)) 3005 } else if ( !context || context.jquery ) { 3006 return ( context || root ).find( selector ); 3007 3008 // HANDLE: $(expr, context) 3009 // (which is just equivalent to: $(context).find(expr) 3010 } else { 3011 return this.constructor( context ).find( selector ); 3012 } 3013 3014 // HANDLE: $(DOMElement) 3015 } else if ( selector.nodeType ) { 3016 this[ 0 ] = selector; 3017 this.length = 1; 3018 return this; 3019 3020 // HANDLE: $(function) 3021 // Shortcut for document ready 3022 } else if ( isFunction( selector ) ) { 3023 return root.ready !== undefined ? 3024 root.ready( selector ) : 3025 3026 // Execute immediately if ready is not present 3027 selector( jQuery ); 3028 } 3029 3030 return jQuery.makeArray( selector, this ); 3031 }; 3032 3033// Give the init function the jQuery prototype for later instantiation 3034init.prototype = jQuery.fn; 3035 3036// Initialize central reference 3037rootjQuery = jQuery( document ); 3038 3039 3040var rparentsprev = /^(?:parents|prev(?:Until|All))/, 3041 3042 // Methods guaranteed to produce a unique set when starting from a unique set 3043 guaranteedUnique = { 3044 children: true, 3045 contents: true, 3046 next: true, 3047 prev: true 3048 }; 3049 3050jQuery.fn.extend( { 3051 has: function( target ) { 3052 var targets = jQuery( target, this ), 3053 l = targets.length; 3054 3055 return this.filter( function() { 3056 var i = 0; 3057 for ( ; i < l; i++ ) { 3058 if ( jQuery.contains( this, targets[ i ] ) ) { 3059 return true; 3060 } 3061 } 3062 } ); 3063 }, 3064 3065 closest: function( selectors, context ) { 3066 var cur, 3067 i = 0, 3068 l = this.length, 3069 matched = [],
vendor: 2,661 bytes, lines 3070-3172
3070 targets = typeof selectors !== "string" && jQuery( selectors ); 3071 3072 // Positional selectors never match, since there's no _selection_ context 3073 if ( !rneedsContext.test( selectors ) ) { 3074 for ( ; i < l; i++ ) { 3075 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { 3076 3077 // Always skip document fragments 3078 if ( cur.nodeType < 11 && ( targets ? 3079 targets.index( cur ) > -1 : 3080 3081 // Don't pass non-elements to Sizzle 3082 cur.nodeType === 1 && 3083 jQuery.find.matchesSelector( cur, selectors ) ) ) { 3084 3085 matched.push( cur ); 3086 break; 3087 } 3088 } 3089 } 3090 } 3091 3092 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); 3093 }, 3094 3095 // Determine the position of an element within the set 3096 index: function( elem ) { 3097 3098 // No argument, return index in parent 3099 if ( !elem ) { 3100 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; 3101 } 3102 3103 // Index in selector 3104 if ( typeof elem === "string" ) { 3105 return indexOf.call( jQuery( elem ), this[ 0 ] ); 3106 } 3107 3108 // Locate the position of the desired element 3109 return indexOf.call( this, 3110 3111 // If it receives a jQuery object, the first element is used 3112 elem.jquery ? elem[ 0 ] : elem 3113 ); 3114 }, 3115 3116 add: function( selector, context ) { 3117 return this.pushStack( 3118 jQuery.uniqueSort( 3119 jQuery.merge( this.get(), jQuery( selector, context ) ) 3120 ) 3121 ); 3122 }, 3123 3124 addBack: function( selector ) { 3125 return this.add( selector == null ? 3126 this.prevObject : this.prevObject.filter( selector ) 3127 ); 3128 } 3129} ); 3130 3131function sibling( cur, dir ) { 3132 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} 3133 return cur; 3134} 3135 3136jQuery.each( { 3137 parent: function( elem ) { 3138 var parent = elem.parentNode; 3139 return parent && parent.nodeType !== 11 ? parent : null; 3140 }, 3141 parents: function( elem ) { 3142 return dir( elem, "parentNode" ); 3143 }, 3144 parentsUntil: function( elem, i, until ) { 3145 return dir( elem, "parentNode", until ); 3146 }, 3147 next: function( elem ) { 3148 return sibling( elem, "nextSibling" ); 3149 }, 3150 prev: function( elem ) { 3151 return sibling( elem, "previousSibling" ); 3152 }, 3153 nextAll: function( elem ) { 3154 return dir( elem, "nextSibling" ); 3155 }, 3156 prevAll: function( elem ) { 3157 return dir( elem, "previousSibling" ); 3158 }, 3159 nextUntil: function( elem, i, until ) { 3160 return dir( elem, "nextSibling", until ); 3161 }, 3162 prevUntil: function( elem, i, until ) { 3163 return dir( elem, "previousSibling", until ); 3164 }, 3165 siblings: function( elem ) { 3166 return siblings( ( elem.parentNode || {} ).firstChild, elem ); 3167 }, 3168 children: function( elem ) { 3169 return siblings( elem.firstChild ); 3170 }, 3171 contents: function( elem ) { 3172 if ( typeof elem.contentDocument !== "undefined" ) {
vendor: 8,463 bytes, lines 3172-3515
3172 3173 return elem.contentDocument; 3174 } 3175 3176 // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only 3177 // Treat the template element as a regular one in browsers that 3178 // don't support it. 3179 if ( nodeName( elem, "template" ) ) { 3180 elem = elem.content || elem; 3181 } 3182 3183 return jQuery.merge( [], elem.childNodes ); 3184 } 3185}, function( name, fn ) { 3186 jQuery.fn[ name ] = function( until, selector ) { 3187 var matched = jQuery.map( this, fn, until ); 3188 3189 if ( name.slice( -5 ) !== "Until" ) { 3190 selector = until; 3191 } 3192 3193 if ( selector && typeof selector === "string" ) { 3194 matched = jQuery.filter( selector, matched ); 3195 } 3196 3197 if ( this.length > 1 ) { 3198 3199 // Remove duplicates 3200 if ( !guaranteedUnique[ name ] ) { 3201 jQuery.uniqueSort( matched ); 3202 } 3203 3204 // Reverse order for parents* and prev-derivatives 3205 if ( rparentsprev.test( name ) ) { 3206 matched.reverse(); 3207 } 3208 } 3209 3210 return this.pushStack( matched ); 3211 }; 3212} ); 3213var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); 3214 3215 3216 3217// Convert String-formatted options into Object-formatted ones 3218function createOptions( options ) { 3219 var object = {}; 3220 jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { 3221 object[ flag ] = true; 3222 } ); 3223 return object; 3224} 3225 3226/* 3227 * Create a callback list using the following parameters: 3228 * 3229 * options: an optional list of space-separated options that will change how 3230 * the callback list behaves or a more traditional option object 3231 * 3232 * By default a callback list will act like an event callback list and can be 3233 * "fired" multiple times. 3234 * 3235 * Possible options: 3236 * 3237 * once: will ensure the callback list can only be fired once (like a Deferred) 3238 * 3239 * memory: will keep track of previous values and will call any callback added 3240 * after the list has been fired right away with the latest "memorized" 3241 * values (like a Deferred) 3242 * 3243 * unique: will ensure a callback can only be added once (no duplicate in the list) 3244 * 3245 * stopOnFalse: interrupt callings when a callback returns false 3246 * 3247 */ 3248jQuery.Callbacks = function( options ) { 3249 3250 // Convert options from String-formatted to Object-formatted if needed 3251 // (we check in cache first) 3252 options = typeof options === "string" ? 3253 createOptions( options ) : 3254 jQuery.extend( {}, options ); 3255 3256 var // Flag to know if list is currently firing 3257 firing, 3258 3259 // Last fire value for non-forgettable lists 3260 memory, 3261 3262 // Flag to know if list was already fired 3263 fired, 3264 3265 // Flag to prevent firing 3266 locked, 3267 3268 // Actual callback list 3269 list = [], 3270 3271 // Queue of execution data for repeatable lists 3272 queue = [], 3273 3274 // Index of currently firing callback (modified by add/remove as needed) 3275 firingIndex = -1, 3276 3277 // Fire callbacks 3278 fire = function() { 3279 3280 // Enforce single-firing 3281 locked = locked || options.once; 3282 3283 // Execute callbacks for all pending executions, 3284 // respecting firingIndex overrides and runtime changes 3285 fired = firing = true; 3286 for ( ; queue.length; firingIndex = -1 ) { 3287 memory = queue.shift(); 3288 while ( ++firingIndex < list.length ) { 3289 3290 // Run callback and check for early termination 3291 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && 3292 options.stopOnFalse ) { 3293 3294 // Jump to end and forget the data so .add doesn't re-fire 3295 firingIndex = list.length; 3296 memory = false; 3297 } 3298 } 3299 } 3300 3301 // Forget the data if we're done with it 3302 if ( !options.memory ) { 3303 memory = false; 3304 } 3305 3306 firing = false; 3307 3308 // Clean up if we're done firing for good 3309 if ( locked ) { 3310 3311 // Keep an empty list if we have data for future add calls 3312 if ( memory ) { 3313 list = []; 3314 3315 // Otherwise, this object is spent 3316 } else { 3317 list = ""; 3318 } 3319 } 3320 }, 3321 3322 // Actual Callbacks object 3323 self = { 3324 3325 // Add a callback or a collection of callbacks to the list 3326 add: function() { 3327 if ( list ) { 3328 3329 // If we have memory from a past run, we should fire after adding 3330 if ( memory && !firing ) { 3331 firingIndex = list.length - 1; 3332 queue.push( memory ); 3333 } 3334 3335 ( function add( args ) { 3336 jQuery.each( args, function( _, arg ) { 3337 if ( isFunction( arg ) ) { 3338 if ( !options.unique || !self.has( arg ) ) { 3339 list.push( arg ); 3340 } 3341 } else if ( arg && arg.length && toType( arg ) !== "string" ) { 3342 3343 // Inspect recursively 3344 add( arg ); 3345 } 3346 } ); 3347 } )( arguments ); 3348 3349 if ( memory && !firing ) { 3350 fire(); 3351 } 3352 } 3353 return this; 3354 }, 3355 3356 // Remove a callback from the list 3357 remove: function() { 3358 jQuery.each( arguments, function( _, arg ) { 3359 var index; 3360 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 3361 list.splice( index, 1 ); 3362 3363 // Handle firing indexes 3364 if ( index <= firingIndex ) { 3365 firingIndex--; 3366 } 3367 } 3368 } ); 3369 return this; 3370 }, 3371 3372 // Check if a given callback is in the list. 3373 // If no argument is given, return whether or not list has callbacks attached. 3374 has: function( fn ) { 3375 return fn ? 3376 jQuery.inArray( fn, list ) > -1 : 3377 list.length > 0; 3378 }, 3379 3380 // Remove all callbacks from the list 3381 empty: function() { 3382 if ( list ) { 3383 list = []; 3384 } 3385 return this; 3386 }, 3387 3388 // Disable .fire and .add 3389 // Abort any current/pending executions 3390 // Clear all callbacks and values 3391 disable: function() { 3392 locked = queue = []; 3393 list = memory = ""; 3394 return this; 3395 }, 3396 disabled: function() { 3397 return !list; 3398 }, 3399 3400 // Disable .fire 3401 // Also disable .add unless we have memory (since it would have no effect) 3402 // Abort any pending executions 3403 lock: function() { 3404 locked = queue = []; 3405 if ( !memory && !firing ) { 3406 list = memory = ""; 3407 } 3408 return this; 3409 }, 3410 locked: function() { 3411 return !!locked; 3412 }, 3413 3414 // Call all callbacks with the given context and arguments 3415 fireWith: function( context, args ) { 3416 if ( !locked ) { 3417 args = args || []; 3418 args = [ context, args.slice ? args.slice() : args ]; 3419 queue.push( args ); 3420 if ( !firing ) { 3421 fire(); 3422 } 3423 } 3424 return this; 3425 }, 3426 3427 // Call all the callbacks with the given arguments 3428 fire: function() { 3429 self.fireWith( this, arguments ); 3430 return this; 3431 }, 3432 3433 // To know if the callbacks have already been called at least once 3434 fired: function() { 3435 return !!fired; 3436 } 3437 }; 3438 3439 return self; 3440}; 3441 3442 3443function Identity( v ) { 3444 return v; 3445} 3446function Thrower( ex ) { 3447 throw ex; 3448} 3449 3450function adoptValue( value, resolve, reject, noValue ) { 3451 var method; 3452 3453 try { 3454 3455 // Check for promise aspect first to privilege synchronous behavior 3456 if ( value && isFunction( ( method = value.promise ) ) ) { 3457 method.call( value ).done( resolve ).fail( reject ); 3458 3459 // Other thenables 3460 } else if ( value && isFunction( ( method = value.then ) ) ) { 3461 method.call( value, resolve, reject ); 3462 3463 // Other non-thenables 3464 } else { 3465 3466 // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: 3467 // * false: [ value ].slice( 0 ) => resolve( value ) 3468 // * true: [ value ].slice( 1 ) => resolve() 3469 resolve.apply( undefined, [ value ].slice( noValue ) ); 3470 } 3471 3472 // For Promises/A+, convert exceptions into rejections 3473 // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in 3474 // Deferred#then to conditionally suppress rejection. 3475 } catch ( value ) { 3476 3477 // Support: Android 4.0 only 3478 // Strict mode functions invoked without .call/.apply get global-object context 3479 reject.apply( undefined, [ value ] ); 3480 } 3481} 3482 3483jQuery.extend( { 3484 3485 Deferred: function( func ) { 3486 var tuples = [ 3487 3488 // action, add listener, callbacks, 3489 // ... .then handlers, argument index, [final state] 3490 [ "notify", "progress", jQuery.Callbacks( "memory" ), 3491 jQuery.Callbacks( "memory" ), 2 ], 3492 [ "resolve", "done", jQuery.Callbacks( "once memory" ), 3493 jQuery.Callbacks( "once memory" ), 0, "resolved" ], 3494 [ "reject", "fail", jQuery.Callbacks( "once memory" ), 3495 jQuery.Callbacks( "once memory" ), 1, "rejected" ] 3496 ], 3497 state = "pending", 3498 promise = { 3499 state: function() { 3500 return state; 3501 }, 3502 always: function() { 3503 deferred.done( arguments ).fail( arguments ); 3504 return this; 3505 }, 3506 "catch": function( fn ) { 3507 return promise.then( null, fn ); 3508 }, 3509 3510 // Keep pipe for back-compat 3511 pipe: function( /* fnDone, fnFail, fnProgress */ ) { 3512 var fns = arguments; 3513 3514 return jQuery.Deferred( function( newDefer ) { 3515 jQuery.each( tuples, function(
vendor: 14,915 bytes, lines 3515-4098
3515i, tuple ) { 3516 3517 // Map tuples (progress, done, fail) to arguments (done, fail, progress) 3518 var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; 3519 3520 // deferred.progress(function() { bind to newDefer or newDefer.notify }) 3521 // deferred.done(function() { bind to newDefer or newDefer.resolve }) 3522 // deferred.fail(function() { bind to newDefer or newDefer.reject }) 3523 deferred[ tuple[ 1 ] ]( function() { 3524 var returned = fn && fn.apply( this, arguments ); 3525 if ( returned && isFunction( returned.promise ) ) { 3526 returned.promise() 3527 .progress( newDefer.notify ) 3528 .done( newDefer.resolve ) 3529 .fail( newDefer.reject ); 3530 } else { 3531 newDefer[ tuple[ 0 ] + "With" ]( 3532 this, 3533 fn ? [ returned ] : arguments 3534 ); 3535 } 3536 } ); 3537 } ); 3538 fns = null; 3539 } ).promise(); 3540 }, 3541 then: function( onFulfilled, onRejected, onProgress ) { 3542 var maxDepth = 0; 3543 function resolve( depth, deferred, handler, special ) { 3544 return function() { 3545 var that = this, 3546 args = arguments, 3547 mightThrow = function() { 3548 var returned, then; 3549 3550 // Support: Promises/A+ section 2.3.3.3.3 3551 // https://promisesaplus.com/#point-59 3552 // Ignore double-resolution attempts 3553 if ( depth < maxDepth ) { 3554 return; 3555 } 3556 3557 returned = handler.apply( that, args ); 3558 3559 // Support: Promises/A+ section 2.3.1 3560 // https://promisesaplus.com/#point-48 3561 if ( returned === deferred.promise() ) { 3562 throw new TypeError( "Thenable self-resolution" ); 3563 } 3564 3565 // Support: Promises/A+ sections 2.3.3.1, 3.5 3566 // https://promisesaplus.com/#point-54 3567 // https://promisesaplus.com/#point-75 3568 // Retrieve `then` only once 3569 then = returned && 3570 3571 // Support: Promises/A+ section 2.3.4 3572 // https://promisesaplus.com/#point-64 3573 // Only check objects and functions for thenability 3574 ( typeof returned === "object" || 3575 typeof returned === "function" ) && 3576 returned.then; 3577 3578 // Handle a returned thenable 3579 if ( isFunction( then ) ) { 3580 3581 // Special processors (notify) just wait for resolution 3582 if ( special ) { 3583 then.call( 3584 returned, 3585 resolve( maxDepth, deferred, Identity, special ), 3586 resolve( maxDepth, deferred, Thrower, special ) 3587 ); 3588 3589 // Normal processors (resolve) also hook into progress 3590 } else { 3591 3592 // ...and disregard older resolution values 3593 maxDepth++; 3594 3595 then.call( 3596 returned, 3597 resolve( maxDepth, deferred, Identity, special ), 3598 resolve( maxDepth, deferred, Thrower, special ), 3599 resolve( maxDepth, deferred, Identity, 3600 deferred.notifyWith ) 3601 ); 3602 } 3603 3604 // Handle all other returned values 3605 } else { 3606 3607 // Only substitute handlers pass on context 3608 // and multiple values (non-spec behavior) 3609 if ( handler !== Identity ) { 3610 that = undefined; 3611 args = [ returned ]; 3612 } 3613 3614 // Process the value(s) 3615 // Default process is resolve 3616 ( special || deferred.resolveWith )( that, args ); 3617 } 3618 }, 3619 3620 // Only normal processors (resolve) catch and reject exceptions 3621 process = special ? 3622 mightThrow : 3623 function() { 3624 try { 3625 mightThrow(); 3626 } catch ( e ) { 3627 3628 if ( jQuery.Deferred.exceptionHook ) { 3629 jQuery.Deferred.exceptionHook( e, 3630 process.stackTrace ); 3631 } 3632 3633 // Support: Promises/A+ section 2.3.3.3.4.1 3634 // https://promisesaplus.com/#point-61 3635 // Ignore post-resolution exceptions 3636 if ( depth + 1 >= maxDepth ) { 3637 3638 // Only substitute handlers pass on context 3639 // and multiple values (non-spec behavior) 3640 if ( handler !== Thrower ) { 3641 that = undefined; 3642 args = [ e ]; 3643 } 3644 3645 deferred.rejectWith( that, args ); 3646 } 3647 } 3648 }; 3649 3650 // Support: Promises/A+ section 2.3.3.3.1 3651 // https://promisesaplus.com/#point-57 3652 // Re-resolve promises immediately to dodge false rejection from 3653 // subsequent errors 3654 if ( depth ) { 3655 process(); 3656 } else { 3657 3658 // Call an optional hook to record the stack, in case of exception 3659 // since it's otherwise lost when execution goes async 3660 if ( jQuery.Deferred.getStackHook ) { 3661 process.stackTrace = jQuery.Deferred.getStackHook(); 3662 } 3663 window.setTimeout( process ); 3664 } 3665 }; 3666 } 3667 3668 return jQuery.Deferred( function( newDefer ) { 3669 3670 // progress_handlers.add( ... ) 3671 tuples[ 0 ][ 3 ].add( 3672 resolve( 3673 0, 3674 newDefer, 3675 isFunction( onProgress ) ? 3676 onProgress : 3677 Identity, 3678 newDefer.notifyWith 3679 ) 3680 ); 3681 3682 // fulfilled_handlers.add( ... ) 3683 tuples[ 1 ][ 3 ].add( 3684 resolve( 3685 0, 3686 newDefer, 3687 isFunction( onFulfilled ) ? 3688 onFulfilled : 3689 Identity 3690 ) 3691 ); 3692 3693 // rejected_handlers.add( ... ) 3694 tuples[ 2 ][ 3 ].add( 3695 resolve( 3696 0, 3697 newDefer, 3698 isFunction( onRejected ) ? 3699 onRejected : 3700 Thrower 3701 ) 3702 ); 3703 } ).promise(); 3704 }, 3705 3706 // Get a promise for this deferred 3707 // If obj is provided, the promise aspect is added to the object 3708 promise: function( obj ) { 3709 return obj != null ? jQuery.extend( obj, promise ) : promise; 3710 } 3711 }, 3712 deferred = {}; 3713 3714 // Add list-specific methods 3715 jQuery.each( tuples, function( i, tuple ) { 3716 var list = tuple[ 2 ], 3717 stateString = tuple[ 5 ]; 3718 3719 // promise.progress = list.add 3720 // promise.done = list.add 3721 // promise.fail = list.add 3722 promise[ tuple[ 1 ] ] = list.add; 3723 3724 // Handle state 3725 if ( stateString ) { 3726 list.add( 3727 function() { 3728 3729 // state = "resolved" (i.e., fulfilled) 3730 // state = "rejected" 3731 state = stateString; 3732 }, 3733 3734 // rejected_callbacks.disable 3735 // fulfilled_callbacks.disable 3736 tuples[ 3 - i ][ 2 ].disable, 3737 3738 // rejected_handlers.disable 3739 // fulfilled_handlers.disable 3740 tuples[ 3 - i ][ 3 ].disable, 3741 3742 // progress_callbacks.lock 3743 tuples[ 0 ][ 2 ].lock, 3744 3745 // progress_handlers.lock 3746 tuples[ 0 ][ 3 ].lock 3747 ); 3748 } 3749 3750 // progress_handlers.fire 3751 // fulfilled_handlers.fire 3752 // rejected_handlers.fire 3753 list.add( tuple[ 3 ].fire ); 3754 3755 // deferred.notify = function() { deferred.notifyWith(...) } 3756 // deferred.resolve = function() { deferred.resolveWith(...) } 3757 // deferred.reject = function() { deferred.rejectWith(...) } 3758 deferred[ tuple[ 0 ] ] = function() { 3759 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); 3760 return this; 3761 }; 3762 3763 // deferred.notifyWith = list.fireWith 3764 // deferred.resolveWith = list.fireWith 3765 // deferred.rejectWith = list.fireWith 3766 deferred[ tuple[ 0 ] + "With" ] = list.fireWith; 3767 } ); 3768 3769 // Make the deferred a promise 3770 promise.promise( deferred ); 3771 3772 // Call given func if any 3773 if ( func ) { 3774 func.call( deferred, deferred ); 3775 } 3776 3777 // All done! 3778 return deferred; 3779 }, 3780 3781 // Deferred helper 3782 when: function( singleValue ) { 3783 var 3784 3785 // count of uncompleted subordinates 3786 remaining = arguments.length, 3787 3788 // count of unprocessed arguments 3789 i = remaining, 3790 3791 // subordinate fulfillment data 3792 resolveContexts = Array( i ), 3793 resolveValues = slice.call( arguments ), 3794 3795 // the master Deferred 3796 master = jQuery.Deferred(), 3797 3798 // subordinate callback factory 3799 updateFunc = function( i ) { 3800 return function( value ) { 3801 resolveContexts[ i ] = this; 3802 resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 3803 if ( !( --remaining ) ) { 3804 master.resolveWith( resolveContexts, resolveValues ); 3805 } 3806 }; 3807 }; 3808 3809 // Single- and empty arguments are adopted like Promise.resolve 3810 if ( remaining <= 1 ) { 3811 adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, 3812 !remaining ); 3813 3814 // Use .then() to unwrap secondary thenables (cf. gh-3000) 3815 if ( master.state() === "pending" || 3816 isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { 3817 3818 return master.then(); 3819 } 3820 } 3821 3822 // Multiple arguments are aggregated like Promise.all array elements 3823 while ( i-- ) { 3824 adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); 3825 } 3826 3827 return master.promise(); 3828 } 3829} ); 3830 3831 3832// These usually indicate a programmer mistake during development, 3833// warn about them ASAP rather than swallowing them by default. 3834var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; 3835 3836jQuery.Deferred.exceptionHook = function( error, stack ) { 3837 3838 // Support: IE 8 - 9 only 3839 // Console exists when dev tools are open, which can happen at any time 3840 if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { 3841 window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); 3842 } 3843}; 3844 3845 3846 3847 3848jQuery.readyException = function( error ) { 3849 window.setTimeout( function() { 3850 throw error; 3851 } ); 3852}; 3853 3854 3855 3856 3857// The deferred used on DOM ready 3858var readyList = jQuery.Deferred(); 3859 3860jQuery.fn.ready = function( fn ) { 3861 3862 readyList 3863 .then( fn ) 3864 3865 // Wrap jQuery.readyException in a function so that the lookup 3866 // happens at the time of error handling instead of callback 3867 // registration. 3868 .catch( function( error ) { 3869 jQuery.readyException( error ); 3870 } ); 3871 3872 return this; 3873}; 3874 3875jQuery.extend( { 3876 3877 // Is the DOM ready to be used? Set to true once it occurs. 3878 isReady: false, 3879 3880 // A counter to track how many items to wait for before 3881 // the ready event fires. See #6781 3882 readyWait: 1, 3883 3884 // Handle when the DOM is ready 3885 ready: function( wait ) { 3886 3887 // Abort if there are pending holds or we're already ready 3888 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 3889 return; 3890 } 3891 3892 // Remember that the DOM is ready 3893 jQuery.isReady = true; 3894 3895 // If a normal DOM Ready event fired, decrement, and wait if need be 3896 if ( wait !== true && --jQuery.readyWait > 0 ) { 3897 return; 3898 } 3899 3900 // If there are functions bound, to execute 3901 readyList.resolveWith( document, [ jQuery ] ); 3902 } 3903} ); 3904 3905jQuery.ready.then = readyList.then; 3906 3907// The ready event handler and self cleanup method 3908function completed() { 3909 document.removeEventListener( "DOMContentLoaded", completed ); 3910 window.removeEventListener( "load", completed ); 3911 jQuery.ready(); 3912} 3913 3914// Catch cases where $(document).ready() is called 3915// after the browser event has already occurred. 3916// Support: IE <=9 - 10 only 3917// Older IE sometimes signals "interactive" too soon 3918if ( document.readyState === "complete" || 3919 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { 3920 3921 // Handle it asynchronously to allow scripts the opportunity to delay ready 3922 window.setTimeout( jQuery.ready ); 3923 3924} else { 3925 3926 // Use the handy event callback 3927 document.addEventListener( "DOMContentLoaded", completed ); 3928 3929 // A fallback to window.onload, that will always work 3930 window.addEventListener( "load", completed ); 3931} 3932 3933 3934 3935 3936// Multifunctional method to get and set values of a collection 3937// The value/s can optionally be executed if it's a function 3938var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 3939 var i = 0, 3940 len = elems.length, 3941 bulk = key == null; 3942 3943 // Sets many values 3944 if ( toType( key ) === "object" ) { 3945 chainable = true; 3946 for ( i in key ) { 3947 access( elems, fn, i, key[ i ], true, emptyGet, raw ); 3948 } 3949 3950 // Sets one value 3951 } else if ( value !== undefined ) { 3952 chainable = true; 3953 3954 if ( !isFunction( value ) ) { 3955 raw = true; 3956 } 3957 3958 if ( bulk ) { 3959 3960 // Bulk operations run against the entire set 3961 if ( raw ) { 3962 fn.call( elems, value ); 3963 fn = null; 3964 3965 // ...except when executing function values 3966 } else { 3967 bulk = fn; 3968 fn = function( elem, key, value ) { 3969 return bulk.call( jQuery( elem ), value ); 3970 }; 3971 } 3972 } 3973 3974 if ( fn ) { 3975 for ( ; i < len; i++ ) { 3976 fn( 3977 elems[ i ], key, raw ? 3978 value : 3979 value.call( elems[ i ], i, fn( elems[ i ], key ) ) 3980 ); 3981 } 3982 } 3983 } 3984 3985 if ( chainable ) { 3986 return elems; 3987 } 3988 3989 // Gets 3990 if ( bulk ) { 3991 return fn.call( elems ); 3992 } 3993 3994 return len ? fn( elems[ 0 ], key ) : emptyGet; 3995}; 3996 3997 3998// Matches dashed string for camelizing 3999var rmsPrefix = /^-ms-/, 4000 rdashAlpha = /-([a-z])/g; 4001 4002// Used by camelCase as callback to replace() 4003function fcamelCase( all, letter ) { 4004 return letter.toUpperCase(); 4005} 4006 4007// Convert dashed to camelCase; used by the css and data modules 4008// Support: IE <=9 - 11, Edge 12 - 15 4009// Microsoft forgot to hump their vendor prefix (#9572) 4010function camelCase( string ) { 4011 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 4012} 4013var acceptData = function( owner ) { 4014 4015 // Accepts only: 4016 // - Node 4017 // - Node.ELEMENT_NODE 4018 // - Node.DOCUMENT_NODE 4019 // - Object 4020 // - Any 4021 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); 4022}; 4023 4024 4025 4026 4027function Data() { 4028 this.expando = jQuery.expando + Data.uid++; 4029} 4030 4031Data.uid = 1; 4032 4033Data.prototype = { 4034 4035 cache: function( owner ) { 4036 4037 // Check if the owner object already has a cache 4038 var value = owner[ this.expando ]; 4039 4040 // If not, create one 4041 if ( !value ) { 4042 value = {}; 4043 4044 // We can accept data for non-element nodes in modern browsers, 4045 // but we should not, see #8335. 4046 // Always return an empty object. 4047 if ( acceptData( owner ) ) { 4048 4049 // If it is a node unlikely to be stringify-ed or looped over 4050 // use plain assignment 4051 if ( owner.nodeType ) { 4052 owner[ this.expando ] = value; 4053 4054 // Otherwise secure it in a non-enumerable property 4055 // configurable must be true to allow the property to be 4056 // deleted when data is removed 4057 } else { 4058 Object.defineProperty( owner, this.expando, { 4059 value: value, 4060 configurable: true 4061 } ); 4062 } 4063 } 4064 } 4065 4066 return value; 4067 }, 4068 set: function( owner, data, value ) { 4069 var prop, 4070 cache = this.cache( owner ); 4071 4072 // Handle: [ owner, key, value ] args 4073 // Always use camelCase key (gh-2257) 4074 if ( typeof data === "string" ) { 4075 cache[ camelCase( data ) ] = value; 4076 4077 // Handle: [ owner, { properties } ] args 4078 } else { 4079 4080 // Copy the properties one-by-one to the cache object 4081 for ( prop in data ) { 4082 cache[ camelCase( prop ) ] = data[ prop ]; 4083 } 4084 } 4085 return cache; 4086 }, 4087 get: function( owner, key ) { 4088 return key === undefined ? 4089 this.cache( owner ) : 4090 4091 // Always use camelCase key (gh-2257) 4092 owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; 4093 }, 4094 access: function( owner, key, value ) { 4095 4096 // In cases where either: 4097 // 4098 // 1. No key was specified
vendor: 8,694 bytes, lines 4099-4457
4099 // 2. A string key was specified, but no value provided 4100 // 4101 // Take the "read" path and allow the get method to determine 4102 // which value to return, respectively either: 4103 // 4104 // 1. The entire cache object 4105 // 2. The data stored at the key 4106 // 4107 if ( key === undefined || 4108 ( ( key && typeof key === "string" ) && value === undefined ) ) { 4109 4110 return this.get( owner, key ); 4111 } 4112 4113 // When the key is not a string, or both a key and value 4114 // are specified, set or extend (existing objects) with either: 4115 // 4116 // 1. An object of properties 4117 // 2. A key and value 4118 // 4119 this.set( owner, key, value ); 4120 4121 // Since the "set" path can have two possible entry points 4122 // return the expected data based on which path was taken[*] 4123 return value !== undefined ? value : key; 4124 }, 4125 remove: function( owner, key ) { 4126 var i, 4127 cache = owner[ this.expando ]; 4128 4129 if ( cache === undefined ) { 4130 return; 4131 } 4132 4133 if ( key !== undefined ) { 4134 4135 // Support array or space separated string of keys 4136 if ( Array.isArray( key ) ) { 4137 4138 // If key is an array of keys... 4139 // We always set camelCase keys, so remove that. 4140 key = key.map( camelCase ); 4141 } else { 4142 key = camelCase( key ); 4143 4144 // If a key with the spaces exists, use it. 4145 // Otherwise, create an array by matching non-whitespace 4146 key = key in cache ? 4147 [ key ] : 4148 ( key.match( rnothtmlwhite ) || [] ); 4149 } 4150 4151 i = key.length; 4152 4153 while ( i-- ) { 4154 delete cache[ key[ i ] ]; 4155 } 4156 } 4157 4158 // Remove the expando if there's no more data 4159 if ( key === undefined || jQuery.isEmptyObject( cache ) ) { 4160 4161 // Support: Chrome <=35 - 45 4162 // Webkit & Blink performance suffers when deleting properties 4163 // from DOM nodes, so set to undefined instead 4164 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) 4165 if ( owner.nodeType ) { 4166 owner[ this.expando ] = undefined; 4167 } else { 4168 delete owner[ this.expando ]; 4169 } 4170 } 4171 }, 4172 hasData: function( owner ) { 4173 var cache = owner[ this.expando ]; 4174 return cache !== undefined && !jQuery.isEmptyObject( cache ); 4175 } 4176}; 4177var dataPriv = new Data(); 4178 4179var dataUser = new Data(); 4180 4181 4182 4183// Implementation Summary 4184// 4185// 1. Enforce API surface and semantic compatibility with 1.9.x branch 4186// 2. Improve the module's maintainability by reducing the storage 4187// paths to a single mechanism. 4188// 3. Use the same single mechanism to support "private" and "user" data. 4189// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 4190// 5. Avoid exposing implementation details on user objects (eg. expando properties) 4191// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 4192 4193var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 4194 rmultiDash = /[A-Z]/g; 4195 4196function getData( data ) { 4197 if ( data === "true" ) { 4198 return true; 4199 } 4200 4201 if ( data === "false" ) { 4202 return false; 4203 } 4204 4205 if ( data === "null" ) { 4206 return null; 4207 } 4208 4209 // Only convert to a number if it doesn't change the string 4210 if ( data === +data + "" ) { 4211 return +data; 4212 } 4213 4214 if ( rbrace.test( data ) ) { 4215 return JSON.parse( data ); 4216 } 4217 4218 return data; 4219} 4220 4221function dataAttr( elem, key, data ) { 4222 var name; 4223 4224 // If nothing was found internally, try to fetch any 4225 // data from the HTML5 data-* attribute 4226 if ( data === undefined && elem.nodeType === 1 ) { 4227 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); 4228 data = elem.getAttribute( name ); 4229 4230 if ( typeof data === "string" ) { 4231 try { 4232 data = getData( data ); 4233 } catch ( e ) {} 4234 4235 // Make sure we set the data so it isn't changed later 4236 dataUser.set( elem, key, data ); 4237 } else { 4238 data = undefined; 4239 } 4240 } 4241 return data; 4242} 4243 4244jQuery.extend( { 4245 hasData: function( elem ) { 4246 return dataUser.hasData( elem ) || dataPriv.hasData( elem ); 4247 }, 4248 4249 data: function( elem, name, data ) { 4250 return dataUser.access( elem, name, data ); 4251 }, 4252 4253 removeData: function( elem, name ) { 4254 dataUser.remove( elem, name ); 4255 }, 4256 4257 // TODO: Now that all calls to _data and _removeData have been replaced 4258 // with direct calls to dataPriv methods, these can be deprecated. 4259 _data: function( elem, name, data ) { 4260 return dataPriv.access( elem, name, data ); 4261 }, 4262 4263 _removeData: function( elem, name ) { 4264 dataPriv.remove( elem, name ); 4265 } 4266} ); 4267 4268jQuery.fn.extend( { 4269 data: function( key, value ) { 4270 var i, name, data, 4271 elem = this[ 0 ], 4272 attrs = elem && elem.attributes; 4273 4274 // Gets all values 4275 if ( key === undefined ) { 4276 if ( this.length ) { 4277 data = dataUser.get( elem ); 4278 4279 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { 4280 i = attrs.length; 4281 while ( i-- ) { 4282 4283 // Support: IE 11 only 4284 // The attrs elements can be null (#14894) 4285 if ( attrs[ i ] ) { 4286 name = attrs[ i ].name; 4287 if ( name.indexOf( "data-" ) === 0 ) { 4288 name = camelCase( name.slice( 5 ) ); 4289 dataAttr( elem, name, data[ name ] ); 4290 } 4291 } 4292 } 4293 dataPriv.set( elem, "hasDataAttrs", true ); 4294 } 4295 } 4296 4297 return data; 4298 } 4299 4300 // Sets multiple values 4301 if ( typeof key === "object" ) { 4302 return this.each( function() { 4303 dataUser.set( this, key ); 4304 } ); 4305 } 4306 4307 return access( this, function( value ) { 4308 var data; 4309 4310 // The calling jQuery object (element matches) is not empty 4311 // (and therefore has an element appears at this[ 0 ]) and the 4312 // `value` parameter was not undefined. An empty jQuery object 4313 // will result in `undefined` for elem = this[ 0 ] which will 4314 // throw an exception if an attempt to read a data cache is made. 4315 if ( elem && value === undefined ) { 4316 4317 // Attempt to get data from the cache 4318 // The key will always be camelCased in Data 4319 data = dataUser.get( elem, key ); 4320 if ( data !== undefined ) { 4321 return data; 4322 } 4323 4324 // Attempt to "discover" the data in 4325 // HTML5 custom data-* attrs 4326 data = dataAttr( elem, key ); 4327 if ( data !== undefined ) { 4328 return data; 4329 } 4330 4331 // We tried really hard, but the data doesn't exist. 4332 return; 4333 } 4334 4335 // Set the data... 4336 this.each( function() { 4337 4338 // We always store the camelCased key 4339 dataUser.set( this, key, value ); 4340 } ); 4341 }, null, value, arguments.length > 1, null, true ); 4342 }, 4343 4344 removeData: function( key ) { 4345 return this.each( function() { 4346 dataUser.remove( this, key ); 4347 } ); 4348 } 4349} ); 4350 4351 4352jQuery.extend( { 4353 queue: function( elem, type, data ) { 4354 var queue; 4355 4356 if ( elem ) { 4357 type = ( type || "fx" ) + "queue"; 4358 queue = dataPriv.get( elem, type ); 4359 4360 // Speed up dequeue by getting out quickly if this is just a lookup 4361 if ( data ) { 4362 if ( !queue || Array.isArray( data ) ) { 4363 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); 4364 } else { 4365 queue.push( data ); 4366 } 4367 } 4368 return queue || []; 4369 } 4370 }, 4371 4372 dequeue: function( elem, type ) { 4373 type = type || "fx"; 4374 4375 var queue = jQuery.queue( elem, type ), 4376 startLength = queue.length, 4377 fn = queue.shift(), 4378 hooks = jQuery._queueHooks( elem, type ), 4379 next = function() { 4380 jQuery.dequeue( elem, type ); 4381 }; 4382 4383 // If the fx queue is dequeued, always remove the progress sentinel 4384 if ( fn === "inprogress" ) { 4385 fn = queue.shift(); 4386 startLength--; 4387 } 4388 4389 if ( fn ) { 4390 4391 // Add a progress sentinel to prevent the fx queue from being 4392 // automatically dequeued 4393 if ( type === "fx" ) { 4394 queue.unshift( "inprogress" ); 4395 } 4396 4397 // Clear up the last queue stop function 4398 delete hooks.stop; 4399 fn.call( elem, next, hooks ); 4400 } 4401 4402 if ( !startLength && hooks ) { 4403 hooks.empty.fire(); 4404 } 4405 }, 4406 4407 // Not public - generate a queueHooks object, or return the current one 4408 _queueHooks: function( elem, type ) { 4409 var key = type + "queueHooks"; 4410 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { 4411 empty: jQuery.Callbacks( "once memory" ).add( function() { 4412 dataPriv.remove( elem, [ type + "queue", key ] ); 4413 } ) 4414 } ); 4415 } 4416} ); 4417 4418jQuery.fn.extend( { 4419 queue: function( type, data ) { 4420 var setter = 2; 4421 4422 if ( typeof type !== "string" ) { 4423 data = type; 4424 type = "fx"; 4425 setter--; 4426 } 4427 4428 if ( arguments.length < setter ) { 4429 return jQuery.queue( this[ 0 ], type ); 4430 } 4431 4432 return data === undefined ? 4433 this : 4434 this.each( function() { 4435 var queue = jQuery.queue( this, type, data ); 4436 4437 // Ensure a hooks for this queue 4438 jQuery._queueHooks( this, type ); 4439 4440 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { 4441 jQuery.dequeue( this, type ); 4442 } 4443 } ); 4444 }, 4445 dequeue: function( type ) { 4446 return this.each( function() { 4447 jQuery.dequeue( this, type ); 4448 } ); 4449 }, 4450 clearQueue: function( type ) { 4451 return this.queue( type || "fx", [] ); 4452 }, 4453 4454 // Get a promise resolved when queues of a certain type 4455 // are emptied (fx is the type by default) 4456 promise: function( type, obj ) { 4457 var tmp,
vendor: 10,491 bytes, lines 4458-4882
4458 count = 1, 4459 defer = jQuery.Deferred(), 4460 elements = this, 4461 i = this.length, 4462 resolve = function() { 4463 if ( !( --count ) ) { 4464 defer.resolveWith( elements, [ elements ] ); 4465 } 4466 }; 4467 4468 if ( typeof type !== "string" ) { 4469 obj = type; 4470 type = undefined; 4471 } 4472 type = type || "fx"; 4473 4474 while ( i-- ) { 4475 tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); 4476 if ( tmp && tmp.empty ) { 4477 count++; 4478 tmp.empty.add( resolve ); 4479 } 4480 } 4481 resolve(); 4482 return defer.promise( obj ); 4483 } 4484} ); 4485var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; 4486 4487var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); 4488 4489 4490var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 4491 4492var documentElement = document.documentElement; 4493 4494 4495 4496 var isAttached = function( elem ) { 4497 return jQuery.contains( elem.ownerDocument, elem ); 4498 }, 4499 composed = { composed: true }; 4500 4501 // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only 4502 // Check attachment across shadow DOM boundaries when possible (gh-3504) 4503 // Support: iOS 10.0-10.2 only 4504 // Early iOS 10 versions support `attachShadow` but not `getRootNode`, 4505 // leading to errors. We need to check for `getRootNode`. 4506 if ( documentElement.getRootNode ) { 4507 isAttached = function( elem ) { 4508 return jQuery.contains( elem.ownerDocument, elem ) || 4509 elem.getRootNode( composed ) === elem.ownerDocument; 4510 }; 4511 } 4512var isHiddenWithinTree = function( elem, el ) { 4513 4514 // isHiddenWithinTree might be called from jQuery#filter function; 4515 // in that case, element will be second argument 4516 elem = el || elem; 4517 4518 // Inline style trumps all 4519 return elem.style.display === "none" || 4520 elem.style.display === "" && 4521 4522 // Otherwise, check computed style 4523 // Support: Firefox <=43 - 45 4524 // Disconnected elements can have computed display: none, so first confirm that elem is 4525 // in the document. 4526 isAttached( elem ) && 4527 4528 jQuery.css( elem, "display" ) === "none"; 4529 }; 4530 4531var swap = function( elem, options, callback, args ) { 4532 var ret, name, 4533 old = {}; 4534 4535 // Remember the old values, and insert the new ones 4536 for ( name in options ) { 4537 old[ name ] = elem.style[ name ]; 4538 elem.style[ name ] = options[ name ]; 4539 } 4540 4541 ret = callback.apply( elem, args || [] ); 4542 4543 // Revert the old values 4544 for ( name in options ) { 4545 elem.style[ name ] = old[ name ]; 4546 } 4547 4548 return ret; 4549}; 4550 4551 4552 4553 4554function adjustCSS( elem, prop, valueParts, tween ) { 4555 var adjusted, scale, 4556 maxIterations = 20, 4557 currentValue = tween ? 4558 function() { 4559 return tween.cur(); 4560 } : 4561 function() { 4562 return jQuery.css( elem, prop, "" ); 4563 }, 4564 initial = currentValue(), 4565 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 4566 4567 // Starting value computation is required for potential unit mismatches 4568 initialInUnit = elem.nodeType && 4569 ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && 4570 rcssNum.exec( jQuery.css( elem, prop ) ); 4571 4572 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { 4573 4574 // Support: Firefox <=54 4575 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) 4576 initial = initial / 2; 4577 4578 // Trust units reported by jQuery.css 4579 unit = unit || initialInUnit[ 3 ]; 4580 4581 // Iteratively approximate from a nonzero starting point 4582 initialInUnit = +initial || 1; 4583 4584 while ( maxIterations-- ) { 4585 4586 // Evaluate and update our best guess (doubling guesses that zero out). 4587 // Finish if the scale equals or crosses 1 (making the old*new product non-positive). 4588 jQuery.style( elem, prop, initialInUnit + unit ); 4589 if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { 4590 maxIterations = 0; 4591 } 4592 initialInUnit = initialInUnit / scale; 4593 4594 } 4595 4596 initialInUnit = initialInUnit * 2; 4597 jQuery.style( elem, prop, initialInUnit + unit ); 4598 4599 // Make sure we update the tween properties later on 4600 valueParts = valueParts || []; 4601 } 4602 4603 if ( valueParts ) { 4604 initialInUnit = +initialInUnit || +initial || 0; 4605 4606 // Apply relative offset (+=/-=) if specified 4607 adjusted = valueParts[ 1 ] ? 4608 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : 4609 +valueParts[ 2 ]; 4610 if ( tween ) { 4611 tween.unit = unit; 4612 tween.start = initialInUnit; 4613 tween.end = adjusted; 4614 } 4615 } 4616 return adjusted; 4617} 4618 4619 4620var defaultDisplayMap = {}; 4621 4622function getDefaultDisplay( elem ) { 4623 var temp, 4624 doc = elem.ownerDocument, 4625 nodeName = elem.nodeName, 4626 display = defaultDisplayMap[ nodeName ]; 4627 4628 if ( display ) { 4629 return display; 4630 } 4631 4632 temp = doc.body.appendChild( doc.createElement( nodeName ) ); 4633 display = jQuery.css( temp, "display" ); 4634 4635 temp.parentNode.removeChild( temp ); 4636 4637 if ( display === "none" ) { 4638 display = "block"; 4639 } 4640 defaultDisplayMap[ nodeName ] = display; 4641 4642 return display; 4643} 4644 4645function showHide( elements, show ) { 4646 var display, elem, 4647 values = [], 4648 index = 0, 4649 length = elements.length; 4650 4651 // Determine new display value for elements that need to change 4652 for ( ; index < length; index++ ) { 4653 elem = elements[ index ]; 4654 if ( !elem.style ) { 4655 continue; 4656 } 4657 4658 display = elem.style.display; 4659 if ( show ) { 4660 4661 // Since we force visibility upon cascade-hidden elements, an immediate (and slow) 4662 // check is required in this first loop unless we have a nonempty display value (either 4663 // inline or about-to-be-restored) 4664 if ( display === "none" ) { 4665 values[ index ] = dataPriv.get( elem, "display" ) || null; 4666 if ( !values[ index ] ) { 4667 elem.style.display = ""; 4668 } 4669 } 4670 if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { 4671 values[ index ] = getDefaultDisplay( elem ); 4672 } 4673 } else { 4674 if ( display !== "none" ) { 4675 values[ index ] = "none"; 4676 4677 // Remember what we're overwriting 4678 dataPriv.set( elem, "display", display ); 4679 } 4680 } 4681 } 4682 4683 // Set the display of the elements in a second loop to avoid constant reflow 4684 for ( index = 0; index < length; index++ ) { 4685 if ( values[ index ] != null ) { 4686 elements[ index ].style.display = values[ index ]; 4687 } 4688 } 4689 4690 return elements; 4691} 4692 4693jQuery.fn.extend( { 4694 show: function() { 4695 return showHide( this, true ); 4696 }, 4697 hide: function() { 4698 return showHide( this ); 4699 }, 4700 toggle: function( state ) { 4701 if ( typeof state === "boolean" ) { 4702 return state ? this.show() : this.hide(); 4703 } 4704 4705 return this.each( function() { 4706 if ( isHiddenWithinTree( this ) ) { 4707 jQuery( this ).show(); 4708 } else { 4709 jQuery( this ).hide(); 4710 } 4711 } ); 4712 } 4713} ); 4714var rcheckableType = ( /^(?:checkbox|radio)$/i ); 4715 4716var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); 4717 4718var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); 4719 4720 4721 4722// We have to close these tags to support XHTML (#13200) 4723var wrapMap = { 4724 4725 // Support: IE <=9 only 4726 option: [ 1, "<select multiple='multiple'>", "</select>" ], 4727 4728 // XHTML parsers do not magically insert elements in the 4729 // same way that tag soup parsers do. So we cannot shorten 4730 // this by omitting <tbody> or other required elements. 4731 thead: [ 1, "<table>", "</table>" ], 4732 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 4733 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 4734 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 4735 4736 _default: [ 0, "", "" ] 4737}; 4738 4739// Support: IE <=9 only 4740wrapMap.optgroup = wrapMap.option; 4741 4742wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 4743wrapMap.th = wrapMap.td; 4744 4745 4746function getAll( context, tag ) { 4747 4748 // Support: IE <=9 - 11 only 4749 // Use typeof to avoid zero-argument method invocation on host objects (#15151) 4750 var ret; 4751 4752 if ( typeof context.getElementsByTagName !== "undefined" ) { 4753 ret = context.getElementsByTagName( tag || "*" ); 4754 4755 } else if ( typeof context.querySelectorAll !== "undefined" ) { 4756 ret = context.querySelectorAll( tag || "*" ); 4757 4758 } else { 4759 ret = []; 4760 } 4761 4762 if ( tag === undefined || tag && nodeName( context, tag ) ) { 4763 return jQuery.merge( [ context ], ret ); 4764 } 4765 4766 return ret; 4767} 4768 4769 4770// Mark scripts as having already been evaluated 4771function setGlobalEval( elems, refElements ) { 4772 var i = 0, 4773 l = elems.length; 4774 4775 for ( ; i < l; i++ ) { 4776 dataPriv.set( 4777 elems[ i ], 4778 "globalEval", 4779 !refElements || dataPriv.get( refElements[ i ], "globalEval" ) 4780 ); 4781 } 4782} 4783 4784 4785var rhtml = /<|&#?\w+;/; 4786 4787function buildFragment( elems, context, scripts, selection, ignored ) { 4788 var elem, tmp, tag, wrap, attached, j, 4789 fragment = context.createDocumentFragment(), 4790 nodes = [], 4791 i = 0, 4792 l = elems.length; 4793 4794 for ( ; i < l; i++ ) { 4795 elem = elems[ i ]; 4796 4797 if ( elem || elem === 0 ) { 4798 4799 // Add nodes directly 4800 if ( toType( elem ) === "object" ) { 4801 4802 // Support: Android <=4.0 only, PhantomJS 1 only 4803 // push.apply(_, arraylike) throws on ancient WebKit 4804 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 4805 4806 // Convert non-html into a text node 4807 } else if ( !rhtml.test( elem ) ) { 4808 nodes.push( context.createTextNode( elem ) ); 4809 4810 // Convert html into DOM nodes 4811 } else { 4812 tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); 4813 4814 // Deserialize a standard representation 4815 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); 4816 wrap = wrapMap[ tag ] || wrapMap._default; 4817 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; 4818 4819 // Descend through wrappers to the right content 4820 j = wrap[ 0 ]; 4821 while ( j-- ) { 4822 tmp = tmp.lastChild; 4823 } 4824 4825 // Support: Android <=4.0 only, PhantomJS 1 only 4826 // push.apply(_, arraylike) throws on ancient WebKit 4827 jQuery.merge( nodes, tmp.childNodes ); 4828 4829 // Remember the top-level container 4830 tmp = fragment.firstChild; 4831 4832 // Ensure the created nodes are orphaned (#12392) 4833 tmp.textContent = ""; 4834 } 4835 } 4836 } 4837 4838 // Remove wrapper from fragment 4839 fragment.textContent = ""; 4840 4841 i = 0; 4842 while ( ( elem = nodes[ i++ ] ) ) { 4843 4844 // Skip elements already in the context collection (trac-4087) 4845 if ( selection && jQuery.inArray( elem, selection ) > -1 ) { 4846 if ( ignored ) { 4847 ignored.push( elem ); 4848 } 4849 continue; 4850 } 4851 4852 attached = isAttached( elem ); 4853 4854 // Append to fragment 4855 tmp = getAll( fragment.appendChild( elem ), "script" ); 4856 4857 // Preserve script evaluation history 4858 if ( attached ) { 4859 setGlobalEval( tmp ); 4860 } 4861 4862 // Capture executables 4863 if ( scripts ) { 4864 j = 0; 4865 while ( ( elem = tmp[ j++ ] ) ) { 4866 if ( rscriptType.test( elem.type || "" ) ) { 4867 scripts.push( elem ); 4868 } 4869 } 4870 } 4871 } 4872 4873 return fragment; 4874} 4875 4876 4877( function() { 4878 var fragment = document.createDocumentFragment(), 4879 div = fragment.appendChild( document.createElement( "div" ) ), 4880 input = document.createElement( "input" ); 4881 4882 // Support: Android 4.0 - 4.3 only
vendor: 11,062 bytes, lines 4883-5265
4883 // Check state lost if the name is set (#11217) 4884 // Support: Windows Web Apps (WWA) 4885 // `name` and `type` must use .setAttribute for WWA (#14901) 4886 input.setAttribute( "type", "radio" ); 4887 input.setAttribute( "checked", "checked" ); 4888 input.setAttribute( "name", "t" ); 4889 4890 div.appendChild( input ); 4891 4892 // Support: Android <=4.1 only 4893 // Older WebKit doesn't clone checked state correctly in fragments 4894 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 4895 4896 // Support: IE <=11 only 4897 // Make sure textarea (and checkbox) defaultValue is properly cloned 4898 div.innerHTML = "<textarea>x</textarea>"; 4899 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 4900} )(); 4901 4902 4903var 4904 rkeyEvent = /^key/, 4905 rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, 4906 rtypenamespace = /^([^.]*)(?:\.(.+)|)/; 4907 4908function returnTrue() { 4909 return true; 4910} 4911 4912function returnFalse() { 4913 return false; 4914} 4915 4916// Support: IE <=9 - 11+ 4917// focus() and blur() are asynchronous, except when they are no-op. 4918// So expect focus to be synchronous when the element is already active, 4919// and blur to be synchronous when the element is not already active. 4920// (focus and blur are always synchronous in other supported browsers, 4921// this just defines when we can count on it). 4922function expectSync( elem, type ) { 4923 return ( elem === safeActiveElement() ) === ( type === "focus" ); 4924} 4925 4926// Support: IE <=9 only 4927// Accessing document.activeElement can throw unexpectedly 4928// https://bugs.jquery.com/ticket/13393 4929function safeActiveElement() { 4930 try { 4931 return document.activeElement; 4932 } catch ( err ) { } 4933} 4934 4935function on( elem, types, selector, data, fn, one ) { 4936 var origFn, type; 4937 4938 // Types can be a map of types/handlers 4939 if ( typeof types === "object" ) { 4940 4941 // ( types-Object, selector, data ) 4942 if ( typeof selector !== "string" ) { 4943 4944 // ( types-Object, data ) 4945 data = data || selector; 4946 selector = undefined; 4947 } 4948 for ( type in types ) { 4949 on( elem, type, selector, data, types[ type ], one ); 4950 } 4951 return elem; 4952 } 4953 4954 if ( data == null && fn == null ) { 4955 4956 // ( types, fn ) 4957 fn = selector; 4958 data = selector = undefined; 4959 } else if ( fn == null ) { 4960 if ( typeof selector === "string" ) { 4961 4962 // ( types, selector, fn ) 4963 fn = data; 4964 data = undefined; 4965 } else { 4966 4967 // ( types, data, fn ) 4968 fn = data; 4969 data = selector; 4970 selector = undefined; 4971 } 4972 } 4973 if ( fn === false ) { 4974 fn = returnFalse; 4975 } else if ( !fn ) { 4976 return elem; 4977 } 4978 4979 if ( one === 1 ) { 4980 origFn = fn; 4981 fn = function( event ) { 4982 4983 // Can use an empty set, since event contains the info 4984 jQuery().off( event ); 4985 return origFn.apply( this, arguments ); 4986 }; 4987 4988 // Use same guid so caller can remove using origFn 4989 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 4990 } 4991 return elem.each( function() { 4992 jQuery.event.add( this, types, fn, data, selector ); 4993 } ); 4994} 4995 4996/* 4997 * Helper functions for managing events -- not part of the public interface. 4998 * Props to Dean Edwards' addEvent library for many of the ideas. 4999 */ 5000jQuery.event = { 5001 5002 global: {}, 5003 5004 add: function( elem, types, handler, data, selector ) { 5005 5006 var handleObjIn, eventHandle, tmp, 5007 events, t, handleObj, 5008 special, handlers, type, namespaces, origType, 5009 elemData = dataPriv.get( elem ); 5010 5011 // Don't attach events to noData or text/comment nodes (but allow plain objects) 5012 if ( !elemData ) { 5013 return; 5014 } 5015 5016 // Caller can pass in an object of custom data in lieu of the handler 5017 if ( handler.handler ) { 5018 handleObjIn = handler; 5019 handler = handleObjIn.handler; 5020 selector = handleObjIn.selector; 5021 } 5022 5023 // Ensure that invalid selectors throw exceptions at attach time 5024 // Evaluate against documentElement in case elem is a non-element node (e.g., document) 5025 if ( selector ) { 5026 jQuery.find.matchesSelector( documentElement, selector ); 5027 } 5028 5029 // Make sure that the handler has a unique ID, used to find/remove it later 5030 if ( !handler.guid ) { 5031 handler.guid = jQuery.guid++; 5032 } 5033 5034 // Init the element's event structure and main handler, if this is the first 5035 if ( !( events = elemData.events ) ) { 5036 events = elemData.events = {}; 5037 } 5038 if ( !( eventHandle = elemData.handle ) ) { 5039 eventHandle = elemData.handle = function( e ) { 5040 5041 // Discard the second event of a jQuery.event.trigger() and 5042 // when an event is called after a page has unloaded 5043 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? 5044 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 5045 }; 5046 } 5047 5048 // Handle multiple events separated by a space 5049 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 5050 t = types.length; 5051 while ( t-- ) { 5052 tmp = rtypenamespace.exec( types[ t ] ) || []; 5053 type = origType = tmp[ 1 ]; 5054 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 5055 5056 // There *must* be a type, no attaching namespace-only handlers 5057 if ( !type ) { 5058 continue; 5059 } 5060 5061 // If event changes its type, use the special event handlers for the changed type 5062 special = jQuery.event.special[ type ] || {}; 5063 5064 // If selector defined, determine special event api type, otherwise given type 5065 type = ( selector ? special.delegateType : special.bindType ) || type; 5066 5067 // Update special based on newly reset type 5068 special = jQuery.event.special[ type ] || {}; 5069 5070 // handleObj is passed to all event handlers 5071 handleObj = jQuery.extend( { 5072 type: type, 5073 origType: origType, 5074 data: data, 5075 handler: handler, 5076 guid: handler.guid, 5077 selector: selector, 5078 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 5079 namespace: namespaces.join( "." ) 5080 }, handleObjIn ); 5081 5082 // Init the event handler queue if we're the first 5083 if ( !( handlers = events[ type ] ) ) { 5084 handlers = events[ type ] = []; 5085 handlers.delegateCount = 0; 5086 5087 // Only use addEventListener if the special events handler returns false 5088 if ( !special.setup || 5089 special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 5090 5091 if ( elem.addEventListener ) { 5092 elem.addEventListener( type, eventHandle ); 5093 } 5094 } 5095 } 5096 5097 if ( special.add ) { 5098 special.add.call( elem, handleObj ); 5099 5100 if ( !handleObj.handler.guid ) { 5101 handleObj.handler.guid = handler.guid; 5102 } 5103 } 5104 5105 // Add to the element's handler list, delegates in front 5106 if ( selector ) { 5107 handlers.splice( handlers.delegateCount++, 0, handleObj ); 5108 } else { 5109 handlers.push( handleObj ); 5110 } 5111 5112 // Keep track of which events have ever been used, for event optimization 5113 jQuery.event.global[ type ] = true; 5114 } 5115 5116 }, 5117 5118 // Detach an event or set of events from an element 5119 remove: function( elem, types, handler, selector, mappedTypes ) { 5120 5121 var j, origCount, tmp, 5122 events, t, handleObj, 5123 special, handlers, type, namespaces, origType, 5124 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); 5125 5126 if ( !elemData || !( events = elemData.events ) ) { 5127 return; 5128 } 5129 5130 // Once for each type.namespace in types; type may be omitted 5131 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 5132 t = types.length; 5133 while ( t-- ) { 5134 tmp = rtypenamespace.exec( types[ t ] ) || []; 5135 type = origType = tmp[ 1 ]; 5136 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 5137 5138 // Unbind all events (on this namespace, if provided) for the element 5139 if ( !type ) { 5140 for ( type in events ) { 5141 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 5142 } 5143 continue; 5144 } 5145 5146 special = jQuery.event.special[ type ] || {}; 5147 type = ( selector ? special.delegateType : special.bindType ) || type; 5148 handlers = events[ type ] || []; 5149 tmp = tmp[ 2 ] && 5150 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); 5151 5152 // Remove matching events 5153 origCount = j = handlers.length; 5154 while ( j-- ) { 5155 handleObj = handlers[ j ]; 5156 5157 if ( ( mappedTypes || origType === handleObj.origType ) && 5158 ( !handler || handler.guid === handleObj.guid ) && 5159 ( !tmp || tmp.test( handleObj.namespace ) ) && 5160 ( !selector || selector === handleObj.selector || 5161 selector === "**" && handleObj.selector ) ) { 5162 handlers.splice( j, 1 ); 5163 5164 if ( handleObj.selector ) { 5165 handlers.delegateCount--; 5166 } 5167 if ( special.remove ) { 5168 special.remove.call( elem, handleObj ); 5169 } 5170 } 5171 } 5172 5173 // Remove generic event handler if we removed something and no more handlers exist 5174 // (avoids potential for endless recursion during removal of special event handlers) 5175 if ( origCount && !handlers.length ) { 5176 if ( !special.teardown || 5177 special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 5178 5179 jQuery.removeEvent( elem, type, elemData.handle ); 5180 } 5181 5182 delete events[ type ]; 5183 } 5184 } 5185 5186 // Remove data and the expando if it's no longer used 5187 if ( jQuery.isEmptyObject( events ) ) { 5188 dataPriv.remove( elem, "handle events" ); 5189 } 5190 }, 5191 5192 dispatch: function( nativeEvent ) { 5193 5194 // Make a writable jQuery.Event from the native event object 5195 var event = jQuery.event.fix( nativeEvent ); 5196 5197 var i, j, ret, matched, handleObj, handlerQueue, 5198 args = new Array( arguments.length ), 5199 handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], 5200 special = jQuery.event.special[ event.type ] || {}; 5201 5202 // Use the fix-ed jQuery.Event rather than the (read-only) native event 5203 args[ 0 ] = event; 5204 5205 for ( i = 1; i < arguments.length; i++ ) { 5206 args[ i ] = arguments[ i ]; 5207 } 5208 5209 event.delegateTarget = this; 5210 5211 // Call the preDispatch hook for the mapped type, and let it bail if desired 5212 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 5213 return; 5214 } 5215 5216 // Determine handlers 5217 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 5218 5219 // Run delegates first; they may want to stop propagation beneath us 5220 i = 0; 5221 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { 5222 event.currentTarget = matched.elem; 5223 5224 j = 0; 5225 while ( ( handleObj = matched.handlers[ j++ ] ) && 5226 !event.isImmediatePropagationStopped() ) { 5227 5228 // If the event is namespaced, then each handler is only invoked if it is 5229 // specially universal or its namespaces are a superset of the event's. 5230 if ( !event.rnamespace || handleObj.namespace === false || 5231 event.rnamespace.test( handleObj.namespace ) ) { 5232 5233 event.handleObj = handleObj; 5234 event.data = handleObj.data; 5235 5236 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || 5237 handleObj.handler ).apply( matched.elem, args ); 5238 5239 if ( ret !== undefined ) { 5240 if ( ( event.result = ret ) === false ) { 5241 event.preventDefault(); 5242 event.stopPropagation(); 5243 } 5244 } 5245 } 5246 } 5247 } 5248 5249 // Call the postDispatch hook for the mapped type 5250 if ( special.postDispatch ) { 5251 special.postDispatch.call( this, event ); 5252 } 5253 5254 return event.result; 5255 }, 5256 5257 handlers: function( event, handlers ) { 5258 var i, handleObj, sel, matchedHandlers, matchedSelectors, 5259 handlerQueue = [], 5260 delegateCount = handlers.delegateCount, 5261 cur = event.target; 5262 5263 // Find delegate handlers 5264 if ( delegateCount && 5265
vendor: 5,718 bytes, lines 5266-5451
5266 // Support: IE <=9 5267 // Black-hole SVG <use> instance trees (trac-13180) 5268 cur.nodeType && 5269 5270 // Support: Firefox <=42 5271 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) 5272 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click 5273 // Support: IE 11 only 5274 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) 5275 !( event.type === "click" && event.button >= 1 ) ) { 5276 5277 for ( ; cur !== this; cur = cur.parentNode || this ) { 5278 5279 // Don't check non-elements (#13208) 5280 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 5281 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { 5282 matchedHandlers = []; 5283 matchedSelectors = {}; 5284 for ( i = 0; i < delegateCount; i++ ) { 5285 handleObj = handlers[ i ]; 5286 5287 // Don't conflict with Object.prototype properties (#13203) 5288 sel = handleObj.selector + " "; 5289 5290 if ( matchedSelectors[ sel ] === undefined ) { 5291 matchedSelectors[ sel ] = handleObj.needsContext ? 5292 jQuery( sel, this ).index( cur ) > -1 : 5293 jQuery.find( sel, this, null, [ cur ] ).length; 5294 } 5295 if ( matchedSelectors[ sel ] ) { 5296 matchedHandlers.push( handleObj ); 5297 } 5298 } 5299 if ( matchedHandlers.length ) { 5300 handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); 5301 } 5302 } 5303 } 5304 } 5305 5306 // Add the remaining (directly-bound) handlers 5307 cur = this; 5308 if ( delegateCount < handlers.length ) { 5309 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); 5310 } 5311 5312 return handlerQueue; 5313 }, 5314 5315 addProp: function( name, hook ) { 5316 Object.defineProperty( jQuery.Event.prototype, name, { 5317 enumerable: true, 5318 configurable: true, 5319 5320 get: isFunction( hook ) ? 5321 function() { 5322 if ( this.originalEvent ) { 5323 return hook( this.originalEvent ); 5324 } 5325 } : 5326 function() { 5327 if ( this.originalEvent ) { 5328 return this.originalEvent[ name ]; 5329 } 5330 }, 5331 5332 set: function( value ) { 5333 Object.defineProperty( this, name, { 5334 enumerable: true, 5335 configurable: true, 5336 writable: true, 5337 value: value 5338 } ); 5339 } 5340 } ); 5341 }, 5342 5343 fix: function( originalEvent ) { 5344 return originalEvent[ jQuery.expando ] ? 5345 originalEvent : 5346 new jQuery.Event( originalEvent ); 5347 }, 5348 5349 special: { 5350 load: { 5351 5352 // Prevent triggered image.load events from bubbling to window.load 5353 noBubble: true 5354 }, 5355 click: { 5356 5357 // Utilize native event to ensure correct state for checkable inputs 5358 setup: function( data ) { 5359 5360 // For mutual compressibility with _default, replace `this` access with a local var. 5361 // `|| data` is dead code meant only to preserve the variable through minification. 5362 var el = this || data; 5363 5364 // Claim the first handler 5365 if ( rcheckableType.test( el.type ) && 5366 el.click && nodeName( el, "input" ) ) { 5367 5368 // dataPriv.set( el, "click", ... ) 5369 leverageNative( el, "click", returnTrue ); 5370 } 5371 5372 // Return false to allow normal processing in the caller 5373 return false; 5374 }, 5375 trigger: function( data ) { 5376 5377 // For mutual compressibility with _default, replace `this` access with a local var. 5378 // `|| data` is dead code meant only to preserve the variable through minification. 5379 var el = this || data; 5380 5381 // Force setup before triggering a click 5382 if ( rcheckableType.test( el.type ) && 5383 el.click && nodeName( el, "input" ) ) { 5384 5385 leverageNative( el, "click" ); 5386 } 5387 5388 // Return non-false to allow normal event-path propagation 5389 return true; 5390 }, 5391 5392 // For cross-browser consistency, suppress native .click() on links 5393 // Also prevent it if we're currently inside a leveraged native-event stack 5394 _default: function( event ) { 5395 var target = event.target; 5396 return rcheckableType.test( target.type ) && 5397 target.click && nodeName( target, "input" ) && 5398 dataPriv.get( target, "click" ) || 5399 nodeName( target, "a" ); 5400 } 5401 }, 5402 5403 beforeunload: { 5404 postDispatch: function( event ) { 5405 5406 // Support: Firefox 20+ 5407 // Firefox doesn't alert if the returnValue field is not set. 5408 if ( event.result !== undefined && event.originalEvent ) { 5409 event.originalEvent.returnValue = event.result; 5410 } 5411 } 5412 } 5413 } 5414}; 5415 5416// Ensure the presence of an event listener that handles manually-triggered 5417// synthetic events by interrupting progress until reinvoked in response to 5418// *native* events that it fires directly, ensuring that state changes have 5419// already occurred before other listeners are invoked. 5420function leverageNative( el, type, expectSync ) { 5421 5422 // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add 5423 if ( !expectSync ) { 5424 if ( dataPriv.get( el, type ) === undefined ) { 5425 jQuery.event.add( el, type, returnTrue ); 5426 } 5427 return; 5428 } 5429 5430 // Register the controller as a special universal handler for all event namespaces 5431 dataPriv.set( el, type, false ); 5432 jQuery.event.add( el, type, { 5433 namespace: false, 5434 handler: function( event ) { 5435 var notAsync, result, 5436 saved = dataPriv.get( this, type ); 5437 5438 if ( ( event.isTrigger & 1 ) && this[ type ] ) { 5439 5440 // Interrupt processing of the outer synthetic .trigger()ed event 5441 // Saved data should be false in such cases, but might be a leftover capture object 5442 // from an async native handler (gh-4350) 5443 if ( !saved.length ) { 5444 5445 // Store arguments for use when handling the inner native event 5446 // There will always be at least one argument (an event object), so this array 5447 // will not be confused with a leftover capture object. 5448 saved = slice.call( arguments ); 5449 dataPriv.set( this, type, saved ); 5450 5451 // Trigger the native event and capture its result
5452 // Support: IE <=9 - 11+ 5453 // focus() and blur() are asynchronous 5454 notAsync = expectSync( this, type ); 5455 this[ type ](); 5456 result = dataPriv.get( this, type ); 5457 if ( saved !== result || notAsync ) { 5458 dataPriv.set( this, type, false ); 5459 } else { 5460 result = {}; 5461 } 5462 if ( saved !== result ) { 5463 5464 // Cancel the outer synthetic event 5465 event.stopImmediatePropagation(); 5466 event.preventDefault(); 5467 return result.value; 5468 } 5469 5470 // If this is an inner synthetic event for an event with a bubbling surrogate 5471 // (focus or blur), assume that the surrogate already propagated from triggering the 5472 // native event and prevent that from happening again here. 5473 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the 5474 // bubbling surrogate propagates *after* the non-bubbling base), but that seems 5475 // less bad than duplication. 5476 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { 5477 event.stopPropagation(); 5478 } 5479 5480 // If this is a native event triggered above, everything is now in order 5481 // Fire an inner synthetic event with the original arguments 5482 } else if ( saved.length ) { 5483 5484 // ...and capture the result 5485 dataPriv.set( this, type, { 5486 value: jQuery.event.trigger( 5487 5488 // Support: IE <=9 - 11+ 5489 // Extend with the prototype to reset the above stopImmediatePropagation() 5490 jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), 5491 saved.slice( 1 ), 5492 this 5493 ) 5494 } ); 5495 5496 // Abort handling of the native event 5497 event.stopImmediatePropagation(); 5498 } 5499 } 5500 } ); 5501} 5502 5503jQuery.removeEvent = function( elem, type, handle ) { 5504 5505 // This "if" is needed for plain objects 5506 if ( elem.removeEventListener ) { 5507 elem.removeEventListener( type, handle ); 5508 } 5509}; 5510 5511jQuery.Event = function( src, props ) { 5512 5513 // Allow instantiation without the 'new' keyword 5514 if ( !( this instanceof jQuery.Event ) ) { 5515 return new jQuery.Event( src, props ); 5516 } 5517 5518 // Event object 5519 if ( src && src.type ) { 5520 this.originalEvent = src; 5521 this.type = src.type; 5522 5523 // Events bubbling up the document may have been marked as prevented 5524 // by a handler lower down the tree; reflect the correct value. 5525 this.isDefaultPrevented = src.defaultPrevented || 5526 src.defaultPrevented === undefined && 5527 5528 // Support: Android <=2.3 only 5529 src.returnValue === false ? 5530 returnTrue : 5531 returnFalse; 5532 5533 // Create target properties 5534 // Support: Safari <=6 - 7 only 5535 // Target should not be a text node (#504, #13143) 5536 this.target = ( src.target && src.target.nodeType === 3 ) ? 5537 src.target.parentNode : 5538 src.target; 5539 5540 this.currentTarget = src.currentTarget; 5541 this.relatedTarget = src.relatedTarget; 5542 5543 // Event type 5544 } else { 5545 this.type = src; 5546 } 5547 5548 // Put explicitly provided properties onto the event object 5549 if ( props ) { 5550 jQuery.extend( this, props ); 5551 } 5552 5553 // Create a timestamp if incoming event doesn't have one 5554 this.timeStamp = src && src.timeStamp || Date.now(); 5555 5556 // Mark it as fixed 5557 this[ jQuery.expando ] = true; 5558}; 5559 5560// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 5561// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 5562jQuery.Event.prototype = { 5563 constructor: jQuery.Event, 5564 isDefaultPrevented: returnFalse, 5565 isPropagationStopped: returnFalse, 5566 isImmediatePropagationStopped: returnFalse, 5567 isSimulated: false, 5568 5569 preventDefault: function() { 5570 var e = this.originalEvent; 5571 5572 this.isDefaultPrevented = returnTrue; 5573 5574 if ( e && !this.isSimulated ) { 5575 e.preventDefault(); 5576 } 5577 }, 5578 stopPropagation: function() { 5579 var e = this.originalEvent; 5580 5581 this.isPropagationStopped = returnTrue; 5582 5583 if ( e && !this.isSimulated ) { 5584 e.stopPropagation(); 5585 } 5586 }, 5587 stopImmediatePropagation: function() { 5588 var e = this.originalEvent; 5589 5590 this.isImmediatePropagationStopped = returnTrue; 5591 5592 if ( e && !this.isSimulated ) { 5593 e.stopImmediatePropagation(); 5594 } 5595 5596 this.stopPropagation(); 5597 } 5598}; 5599 5600// Includes all common event props including KeyEvent and MouseEvent specific props 5601jQuery.each( { 5602 altKey: true, 5603 bubbles: true, 5604 cancelable: true, 5605 changedTouches: true, 5606 ctrlKey: true, 5607 detail: true, 5608 eventPhase: true, 5609 metaKey: true, 5610 pageX: true, 5611 pageY: true, 5612 shiftKey: true, 5613 view: true, 5614 "char": true, 5615 code: true, 5616 charCode: true, 5617 key: true, 5618 keyCode: true, 5619 button: true, 5620 buttons: true, 5621 clientX: true, 5622 clientY: true, 5623 offsetX: true, 5624 offsetY: true, 5625 pointerId: true, 5626 pointerType: true, 5627 screenX: true, 5628 screenY: true, 5629 targetTouches: true, 5630 toElement: true, 5631 touches: true, 5632 5633 which: function( event ) { 5634 var button = event.button; 5635 5636 // Add which for key events 5637 if ( event.which == null && rkeyEvent.test( event.type ) ) { 5638 return event.charCode != null ? event.charCode : event.keyCode; 5639 } 5640 5641 // Add which for click: 1 === left; 2 === middle; 3 === right 5642 if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { 5643 if ( button & 1 ) { 5644 return 1; 5645 } 5646 5647 if ( button & 2 ) { 5648 return 3; 5649 } 5650 5651 if ( button & 4 ) { 5652 return 2; 5653 } 5654 5655 return 0; 5656 } 5657 5658 return event.which; 5659 } 5660}, jQuery.event.addProp ); 5661 5662jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { 5663 jQuery.event.special[ type ] = { 5664 5665 // Utilize native event if possible so blur/focus sequence is correct 5666 setup: function() { 5667 5668 // Claim the first handler 5669 // dataPriv.set( this, "focus", ... ) 5670 // dataPriv.set( this, "blur", ... ) 5671 leverageNative( this, type, expectSync ); 5672 5673 // Return false to allow normal processing in the caller 5674 return false;
vendor: 8,337 bytes, lines 5675-5985
5675 }, 5676 trigger: function() { 5677 5678 // Force setup before trigger 5679 leverageNative( this, type ); 5680 5681 // Return non-false to allow normal event-path propagation 5682 return true; 5683 }, 5684 5685 delegateType: delegateType 5686 }; 5687} ); 5688 5689// Create mouseenter/leave events using mouseover/out and event-time checks 5690// so that event delegation works in jQuery. 5691// Do the same for pointerenter/pointerleave and pointerover/pointerout 5692// 5693// Support: Safari 7 only 5694// Safari sends mouseenter too often; see: 5695// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 5696// for the description of the bug (it existed in older Chrome versions as well). 5697jQuery.each( { 5698 mouseenter: "mouseover", 5699 mouseleave: "mouseout", 5700 pointerenter: "pointerover", 5701 pointerleave: "pointerout" 5702}, function( orig, fix ) { 5703 jQuery.event.special[ orig ] = { 5704 delegateType: fix, 5705 bindType: fix, 5706 5707 handle: function( event ) { 5708 var ret, 5709 target = this, 5710 related = event.relatedTarget, 5711 handleObj = event.handleObj; 5712 5713 // For mouseenter/leave call the handler if related is outside the target. 5714 // NB: No relatedTarget if the mouse left/entered the browser window 5715 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { 5716 event.type = handleObj.origType; 5717 ret = handleObj.handler.apply( this, arguments ); 5718 event.type = fix; 5719 } 5720 return ret; 5721 } 5722 }; 5723} ); 5724 5725jQuery.fn.extend( { 5726 5727 on: function( types, selector, data, fn ) { 5728 return on( this, types, selector, data, fn ); 5729 }, 5730 one: function( types, selector, data, fn ) { 5731 return on( this, types, selector, data, fn, 1 ); 5732 }, 5733 off: function( types, selector, fn ) { 5734 var handleObj, type; 5735 if ( types && types.preventDefault && types.handleObj ) { 5736 5737 // ( event ) dispatched jQuery.Event 5738 handleObj = types.handleObj; 5739 jQuery( types.delegateTarget ).off( 5740 handleObj.namespace ? 5741 handleObj.origType + "." + handleObj.namespace : 5742 handleObj.origType, 5743 handleObj.selector, 5744 handleObj.handler 5745 ); 5746 return this; 5747 } 5748 if ( typeof types === "object" ) { 5749 5750 // ( types-object [, selector] ) 5751 for ( type in types ) { 5752 this.off( type, selector, types[ type ] ); 5753 } 5754 return this; 5755 } 5756 if ( selector === false || typeof selector === "function" ) { 5757 5758 // ( types [, fn] ) 5759 fn = selector; 5760 selector = undefined; 5761 } 5762 if ( fn === false ) { 5763 fn = returnFalse; 5764 } 5765 return this.each( function() { 5766 jQuery.event.remove( this, types, fn, selector ); 5767 } ); 5768 } 5769} ); 5770 5771 5772var 5773 5774 /* eslint-disable max-len */ 5775 5776 // See https://github.com/eslint/eslint/issues/3229 5777 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, 5778 5779 /* eslint-enable */ 5780 5781 // Support: IE <=10 - 11, Edge 12 - 13 only 5782 // In IE/Edge using regex groups here causes severe slowdowns. 5783 // See https://connect.microsoft.com/IE/feedback/details/1736512/ 5784 rnoInnerhtml = /<script|<style|<link/i, 5785 5786 // checked="checked" or checked 5787 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 5788 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; 5789 5790// Prefer a tbody over its parent table for containing new rows 5791function manipulationTarget( elem, content ) { 5792 if ( nodeName( elem, "table" ) && 5793 nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { 5794 5795 return jQuery( elem ).children( "tbody" )[ 0 ] || elem; 5796 } 5797 5798 return elem; 5799} 5800 5801// Replace/restore the type attribute of script elements for safe DOM manipulation 5802function disableScript( elem ) { 5803 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; 5804 return elem; 5805} 5806function restoreScript( elem ) { 5807 if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { 5808 elem.type = elem.type.slice( 5 ); 5809 } else { 5810 elem.removeAttribute( "type" ); 5811 } 5812 5813 return elem; 5814} 5815 5816function cloneCopyEvent( src, dest ) { 5817 var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; 5818 5819 if ( dest.nodeType !== 1 ) { 5820 return; 5821 } 5822 5823 // 1. Copy private data: events, handlers, etc. 5824 if ( dataPriv.hasData( src ) ) { 5825 pdataOld = dataPriv.access( src ); 5826 pdataCur = dataPriv.set( dest, pdataOld ); 5827 events = pdataOld.events; 5828 5829 if ( events ) { 5830 delete pdataCur.handle; 5831 pdataCur.events = {}; 5832 5833 for ( type in events ) { 5834 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 5835 jQuery.event.add( dest, type, events[ type ][ i ] ); 5836 } 5837 } 5838 } 5839 } 5840 5841 // 2. Copy user data 5842 if ( dataUser.hasData( src ) ) { 5843 udataOld = dataUser.access( src ); 5844 udataCur = jQuery.extend( {}, udataOld ); 5845 5846 dataUser.set( dest, udataCur ); 5847 } 5848} 5849 5850// Fix IE bugs, see support tests 5851function fixInput( src, dest ) { 5852 var nodeName = dest.nodeName.toLowerCase(); 5853 5854 // Fails to persist the checked state of a cloned checkbox or radio button. 5855 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 5856 dest.checked = src.checked; 5857 5858 // Fails to return the selected option to the default selected state when cloning options 5859 } else if ( nodeName === "input" || nodeName === "textarea" ) { 5860 dest.defaultValue = src.defaultValue; 5861 } 5862} 5863 5864function domManip( collection, args, callback, ignored ) { 5865 5866 // Flatten any nested arrays 5867 args = concat.apply( [], args ); 5868 5869 var fragment, first, scripts, hasScripts, node, doc, 5870 i = 0, 5871 l = collection.length, 5872 iNoClone = l - 1, 5873 value = args[ 0 ], 5874 valueIsFunction = isFunction( value ); 5875 5876 // We can't cloneNode fragments that contain checked, in WebKit 5877 if ( valueIsFunction || 5878 ( l > 1 && typeof value === "string" && 5879 !support.checkClone && rchecked.test( value ) ) ) { 5880 return collection.each( function( index ) { 5881 var self = collection.eq( index ); 5882 if ( valueIsFunction ) { 5883 args[ 0 ] = value.call( this, index, self.html() ); 5884 } 5885 domManip( self, args, callback, ignored ); 5886 } ); 5887 } 5888 5889 if ( l ) { 5890 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); 5891 first = fragment.firstChild; 5892 5893 if ( fragment.childNodes.length === 1 ) { 5894 fragment = first; 5895 } 5896 5897 // Require either new content or an interest in ignored elements to invoke the callback 5898 if ( first || ignored ) { 5899 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 5900 hasScripts = scripts.length; 5901 5902 // Use the original fragment for the last item 5903 // instead of the first because it can end up 5904 // being emptied incorrectly in certain situations (#8070). 5905 for ( ; i < l; i++ ) { 5906 node = fragment; 5907 5908 if ( i !== iNoClone ) { 5909 node = jQuery.clone( node, true, true ); 5910 5911 // Keep references to cloned scripts for later restoration 5912 if ( hasScripts ) { 5913 5914 // Support: Android <=4.0 only, PhantomJS 1 only 5915 // push.apply(_, arraylike) throws on ancient WebKit 5916 jQuery.merge( scripts, getAll( node, "script" ) ); 5917 } 5918 } 5919 5920 callback.call( collection[ i ], node, i ); 5921 } 5922 5923 if ( hasScripts ) { 5924 doc = scripts[ scripts.length - 1 ].ownerDocument; 5925 5926 // Reenable scripts 5927 jQuery.map( scripts, restoreScript ); 5928 5929 // Evaluate executable scripts on first document insertion 5930 for ( i = 0; i < hasScripts; i++ ) { 5931 node = scripts[ i ]; 5932 if ( rscriptType.test( node.type || "" ) && 5933 !dataPriv.access( node, "globalEval" ) && 5934 jQuery.contains( doc, node ) ) { 5935 5936 if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { 5937 5938 // Optional AJAX dependency, but won't run scripts if not present 5939 if ( jQuery._evalUrl && !node.noModule ) { 5940 jQuery._evalUrl( node.src, { 5941 nonce: node.nonce || node.getAttribute( "nonce" ) 5942 } ); 5943 } 5944 } else { 5945 DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); 5946 } 5947 } 5948 } 5949 } 5950 } 5951 } 5952 5953 return collection; 5954} 5955 5956function remove( elem, selector, keepData ) { 5957 var node, 5958 nodes = selector ? jQuery.filter( selector, elem ) : elem, 5959 i = 0; 5960 5961 for ( ; ( node = nodes[ i ] ) != null; i++ ) { 5962 if ( !keepData && node.nodeType === 1 ) { 5963 jQuery.cleanData( getAll( node ) ); 5964 } 5965 5966 if ( node.parentNode ) { 5967 if ( keepData && isAttached( node ) ) { 5968 setGlobalEval( getAll( node, "script" ) ); 5969 } 5970 node.parentNode.removeChild( node ); 5971 } 5972 } 5973 5974 return elem; 5975} 5976 5977jQuery.extend( { 5978 htmlPrefilter: function( html ) { 5979 return html.replace( rxhtmlTag, "<$1></$2>" ); 5980 }, 5981 5982 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 5983 var i, l, srcElements, destElements, 5984 clone = elem.cloneNode( true ), 5985 inPage = isAttached(
vendor: 5,988 bytes, lines 5985-6225
5985 elem ); 5986 5987 // Fix IE cloning issues 5988 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && 5989 !jQuery.isXMLDoc( elem ) ) { 5990 5991 // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 5992 destElements = getAll( clone ); 5993 srcElements = getAll( elem ); 5994 5995 for ( i = 0, l = srcElements.length; i < l; i++ ) { 5996 fixInput( srcElements[ i ], destElements[ i ] ); 5997 } 5998 } 5999 6000 // Copy the events from the original to the clone 6001 if ( dataAndEvents ) { 6002 if ( deepDataAndEvents ) { 6003 srcElements = srcElements || getAll( elem ); 6004 destElements = destElements || getAll( clone ); 6005 6006 for ( i = 0, l = srcElements.length; i < l; i++ ) { 6007 cloneCopyEvent( srcElements[ i ], destElements[ i ] ); 6008 } 6009 } else { 6010 cloneCopyEvent( elem, clone ); 6011 } 6012 } 6013 6014 // Preserve script evaluation history 6015 destElements = getAll( clone, "script" ); 6016 if ( destElements.length > 0 ) { 6017 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 6018 } 6019 6020 // Return the cloned set 6021 return clone; 6022 }, 6023 6024 cleanData: function( elems ) { 6025 var data, elem, type, 6026 special = jQuery.event.special, 6027 i = 0; 6028 6029 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { 6030 if ( acceptData( elem ) ) { 6031 if ( ( data = elem[ dataPriv.expando ] ) ) { 6032 if ( data.events ) { 6033 for ( type in data.events ) { 6034 if ( special[ type ] ) { 6035 jQuery.event.remove( elem, type ); 6036 6037 // This is a shortcut to avoid jQuery.event.remove's overhead 6038 } else { 6039 jQuery.removeEvent( elem, type, data.handle ); 6040 } 6041 } 6042 } 6043 6044 // Support: Chrome <=35 - 45+ 6045 // Assign undefined instead of using delete, see Data#remove 6046 elem[ dataPriv.expando ] = undefined; 6047 } 6048 if ( elem[ dataUser.expando ] ) { 6049 6050 // Support: Chrome <=35 - 45+ 6051 // Assign undefined instead of using delete, see Data#remove 6052 elem[ dataUser.expando ] = undefined; 6053 } 6054 } 6055 } 6056 } 6057} ); 6058 6059jQuery.fn.extend( { 6060 detach: function( selector ) { 6061 return remove( this, selector, true ); 6062 }, 6063 6064 remove: function( selector ) { 6065 return remove( this, selector ); 6066 }, 6067 6068 text: function( value ) { 6069 return access( this, function( value ) { 6070 return value === undefined ? 6071 jQuery.text( this ) : 6072 this.empty().each( function() { 6073 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6074 this.textContent = value; 6075 } 6076 } ); 6077 }, null, value, arguments.length ); 6078 }, 6079 6080 append: function() { 6081 return domManip( this, arguments, function( elem ) { 6082 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6083 var target = manipulationTarget( this, elem ); 6084 target.appendChild( elem ); 6085 } 6086 } ); 6087 }, 6088 6089 prepend: function() { 6090 return domManip( this, arguments, function( elem ) { 6091 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6092 var target = manipulationTarget( this, elem ); 6093 target.insertBefore( elem, target.firstChild ); 6094 } 6095 } ); 6096 }, 6097 6098 before: function() { 6099 return domManip( this, arguments, function( elem ) { 6100 if ( this.parentNode ) { 6101 this.parentNode.insertBefore( elem, this ); 6102 } 6103 } ); 6104 }, 6105 6106 after: function() { 6107 return domManip( this, arguments, function( elem ) { 6108 if ( this.parentNode ) { 6109 this.parentNode.insertBefore( elem, this.nextSibling ); 6110 } 6111 } ); 6112 }, 6113 6114 empty: function() { 6115 var elem, 6116 i = 0; 6117 6118 for ( ; ( elem = this[ i ] ) != null; i++ ) { 6119 if ( elem.nodeType === 1 ) { 6120 6121 // Prevent memory leaks 6122 jQuery.cleanData( getAll( elem, false ) ); 6123 6124 // Remove any remaining nodes 6125 elem.textContent = ""; 6126 } 6127 } 6128 6129 return this; 6130 }, 6131 6132 clone: function( dataAndEvents, deepDataAndEvents ) { 6133 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 6134 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 6135 6136 return this.map( function() { 6137 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 6138 } ); 6139 }, 6140 6141 html: function( value ) { 6142 return access( this, function( value ) { 6143 var elem = this[ 0 ] || {}, 6144 i = 0, 6145 l = this.length; 6146 6147 if ( value === undefined && elem.nodeType === 1 ) { 6148 return elem.innerHTML; 6149 } 6150 6151 // See if we can take a shortcut and just use innerHTML 6152 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 6153 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { 6154 6155 value = jQuery.htmlPrefilter( value ); 6156 6157 try { 6158 for ( ; i < l; i++ ) { 6159 elem = this[ i ] || {}; 6160 6161 // Remove element nodes and prevent memory leaks 6162 if ( elem.nodeType === 1 ) { 6163 jQuery.cleanData( getAll( elem, false ) ); 6164 elem.innerHTML = value; 6165 } 6166 } 6167 6168 elem = 0; 6169 6170 // If using innerHTML throws an exception, use the fallback method 6171 } catch ( e ) {} 6172 } 6173 6174 if ( elem ) { 6175 this.empty().append( value ); 6176 } 6177 }, null, value, arguments.length ); 6178 }, 6179 6180 replaceWith: function() { 6181 var ignored = []; 6182 6183 // Make the changes, replacing each non-ignored context element with the new content 6184 return domManip( this, arguments, function( elem ) { 6185 var parent = this.parentNode; 6186 6187 if ( jQuery.inArray( this, ignored ) < 0 ) { 6188 jQuery.cleanData( getAll( this ) ); 6189 if ( parent ) { 6190 parent.replaceChild( elem, this ); 6191 } 6192 } 6193 6194 // Force callback invocation 6195 }, ignored ); 6196 } 6197} ); 6198 6199jQuery.each( { 6200 appendTo: "append", 6201 prependTo: "prepend", 6202 insertBefore: "before", 6203 insertAfter: "after", 6204 replaceAll: "replaceWith" 6205}, function( name, original ) { 6206 jQuery.fn[ name ] = function( selector ) { 6207 var elems, 6208 ret = [], 6209 insert = jQuery( selector ), 6210 last = insert.length - 1, 6211 i = 0; 6212 6213 for ( ; i <= last; i++ ) { 6214 elems = i === last ? this : this.clone( true ); 6215 jQuery( insert[ i ] )[ original ]( elems ); 6216 6217 // Support: Android <=4.0 only, PhantomJS 1 only 6218 // .get() because push.apply(_, arraylike) throws on ancient WebKit 6219 push.apply( ret, elems.get() ); 6220 } 6221 6222 return this.pushStack( ret ); 6223 }; 6224} ); 6225var r
6225numnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 6226 6227var getStyles = function( elem ) { 6228 6229 // Support: IE <=11 only, Firefox <=30 (#15098, #14150) 6230 // IE throws on elements created in popups 6231 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 6232 var view = elem.ownerDocument.defaultView; 6233 6234 if ( !view || !view.opener ) { 6235 view = window; 6236 } 6237 6238 return view.getComputedStyle( elem ); 6239 }; 6240 6241var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); 6242 6243 6244 6245( function() { 6246 6247 // Executing both pixelPosition & boxSizingReliable tests require only one layout 6248 // so they're executed at the same time to save the second computation. 6249 function computeStyleTests() { 6250 6251 // This is a singleton, we need to execute it only once 6252 if ( !div ) { 6253 return; 6254 } 6255 6256 container.style.cssText = "position:absolute;
vendor: 24,862 bytes, lines 6256-7147
6256left:-11111px;width:60px;" + 6257 "margin-top:1px;padding:0;border:0"; 6258 div.style.cssText = 6259 "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + 6260 "margin:auto;border:1px;padding:1px;" + 6261 "width:60%;top:1%"; 6262 documentElement.appendChild( container ).appendChild( div ); 6263 6264 var divStyle = window.getComputedStyle( div ); 6265 pixelPositionVal = divStyle.top !== "1%"; 6266 6267 // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 6268 reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; 6269 6270 // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 6271 // Some styles come back with percentage values, even though they shouldn't 6272 div.style.right = "60%"; 6273 pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; 6274 6275 // Support: IE 9 - 11 only 6276 // Detect misreporting of content dimensions for box-sizing:border-box elements 6277 boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; 6278 6279 // Support: IE 9 only 6280 // Detect overflow:scroll screwiness (gh-3699) 6281 // Support: Chrome <=64 6282 // Don't get tricked when zoom affects offsetWidth (gh-4029) 6283 div.style.position = "absolute"; 6284 scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; 6285 6286 documentElement.removeChild( container ); 6287 6288 // Nullify the div so it wouldn't be stored in the memory and 6289 // it will also be a sign that checks already performed 6290 div = null; 6291 } 6292 6293 function roundPixelMeasures( measure ) { 6294 return Math.round( parseFloat( measure ) ); 6295 } 6296 6297 var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, 6298 reliableMarginLeftVal, 6299 container = document.createElement( "div" ), 6300 div = document.createElement( "div" ); 6301 6302 // Finish early in limited (non-browser) environments 6303 if ( !div.style ) { 6304 return; 6305 } 6306 6307 // Support: IE <=9 - 11 only 6308 // Style of cloned element affects source element cloned (#8908) 6309 div.style.backgroundClip = "content-box"; 6310 div.cloneNode( true ).style.backgroundClip = ""; 6311 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 6312 6313 jQuery.extend( support, { 6314 boxSizingReliable: function() { 6315 computeStyleTests(); 6316 return boxSizingReliableVal; 6317 }, 6318 pixelBoxStyles: function() { 6319 computeStyleTests(); 6320 return pixelBoxStylesVal; 6321 }, 6322 pixelPosition: function() { 6323 computeStyleTests(); 6324 return pixelPositionVal; 6325 }, 6326 reliableMarginLeft: function() { 6327 computeStyleTests(); 6328 return reliableMarginLeftVal; 6329 }, 6330 scrollboxSize: function() { 6331 computeStyleTests(); 6332 return scrollboxSizeVal; 6333 } 6334 } ); 6335} )(); 6336 6337 6338function curCSS( elem, name, computed ) { 6339 var width, minWidth, maxWidth, ret, 6340 6341 // Support: Firefox 51+ 6342 // Retrieving style before computed somehow 6343 // fixes an issue with getting wrong values 6344 // on detached elements 6345 style = elem.style; 6346 6347 computed = computed || getStyles( elem ); 6348 6349 // getPropertyValue is needed for: 6350 // .css('filter') (IE 9 only, #12537) 6351 // .css('--customProperty) (#3144) 6352 if ( computed ) { 6353 ret = computed.getPropertyValue( name ) || computed[ name ]; 6354 6355 if ( ret === "" && !isAttached( elem ) ) { 6356 ret = jQuery.style( elem, name ); 6357 } 6358 6359 // A tribute to the "awesome hack by Dean Edwards" 6360 // Android Browser returns percentage for some values, 6361 // but width seems to be reliably pixels. 6362 // This is against the CSSOM draft spec: 6363 // https://drafts.csswg.org/cssom/#resolved-values 6364 if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { 6365 6366 // Remember the original values 6367 width = style.width; 6368 minWidth = style.minWidth; 6369 maxWidth = style.maxWidth; 6370 6371 // Put in the new values to get a computed value out 6372 style.minWidth = style.maxWidth = style.width = ret; 6373 ret = computed.width; 6374 6375 // Revert the changed values 6376 style.width = width; 6377 style.minWidth = minWidth; 6378 style.maxWidth = maxWidth; 6379 } 6380 } 6381 6382 return ret !== undefined ? 6383 6384 // Support: IE <=9 - 11 only 6385 // IE returns zIndex value as an integer. 6386 ret + "" : 6387 ret; 6388} 6389 6390 6391function addGetHookIf( conditionFn, hookFn ) { 6392 6393 // Define the hook, we'll check on the first run if it's really needed. 6394 return { 6395 get: function() { 6396 if ( conditionFn() ) { 6397 6398 // Hook not needed (or it's not possible to use it due 6399 // to missing dependency), remove it. 6400 delete this.get; 6401 return; 6402 } 6403 6404 // Hook needed; redefine it so that the support test is not executed again. 6405 return ( this.get = hookFn ).apply( this, arguments ); 6406 } 6407 }; 6408} 6409 6410 6411var cssPrefixes = [ "Webkit", "Moz", "ms" ], 6412 emptyStyle = document.createElement( "div" ).style, 6413 vendorProps = {}; 6414 6415// Return a vendor-prefixed property or undefined 6416function vendorPropName( name ) { 6417 6418 // Check for vendor prefixed names 6419 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), 6420 i = cssPrefixes.length; 6421 6422 while ( i-- ) { 6423 name = cssPrefixes[ i ] + capName; 6424 if ( name in emptyStyle ) { 6425 return name; 6426 } 6427 } 6428} 6429 6430// Return a potentially-mapped jQuery.cssProps or vendor prefixed property 6431function finalPropName( name ) { 6432 var final = jQuery.cssProps[ name ] || vendorProps[ name ]; 6433 6434 if ( final ) { 6435 return final; 6436 } 6437 if ( name in emptyStyle ) { 6438 return name; 6439 } 6440 return vendorProps[ name ] = vendorPropName( name ) || name; 6441} 6442 6443 6444var 6445 6446 // Swappable if display is none or starts with table 6447 // except "table", "table-cell", or "table-caption" 6448 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 6449 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 6450 rcustomProp = /^--/, 6451 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 6452 cssNormalTransform = { 6453 letterSpacing: "0", 6454 fontWeight: "400" 6455 }; 6456 6457function setPositiveNumber( elem, value, subtract ) { 6458 6459 // Any relative (+/-) values have already been 6460 // normalized at this point 6461 var matches = rcssNum.exec( value ); 6462 return matches ? 6463 6464 // Guard against undefined "subtract", e.g., when used as in cssHooks 6465 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : 6466 value; 6467} 6468 6469function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { 6470 var i = dimension === "width" ? 1 : 0, 6471 extra = 0, 6472 delta = 0; 6473 6474 // Adjustment may not be necessary 6475 if ( box === ( isBorderBox ? "border" : "content" ) ) { 6476 return 0; 6477 } 6478 6479 for ( ; i < 4; i += 2 ) { 6480 6481 // Both box models exclude margin 6482 if ( box === "margin" ) { 6483 delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); 6484 } 6485 6486 // If we get here with a content-box, we're seeking "padding" or "border" or "margin" 6487 if ( !isBorderBox ) { 6488 6489 // Add padding 6490 delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6491 6492 // For "border" or "margin", add border 6493 if ( box !== "padding" ) { 6494 delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6495 6496 // But still keep track of it otherwise 6497 } else { 6498 extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6499 } 6500 6501 // If we get here with a border-box (content + padding + border), we're seeking "content" or 6502 // "padding" or "margin" 6503 } else { 6504 6505 // For "content", subtract padding 6506 if ( box === "content" ) { 6507 delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6508 } 6509 6510 // For "content" or "padding", subtract border 6511 if ( box !== "margin" ) { 6512 delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6513 } 6514 } 6515 } 6516 6517 // Account for positive content-box scroll gutter when requested by providing computedVal 6518 if ( !isBorderBox && computedVal >= 0 ) { 6519 6520 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 6521 // Assuming integer scroll gutter, subtract the rest and round down 6522 delta += Math.max( 0, Math.ceil( 6523 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 6524 computedVal - 6525 delta - 6526 extra - 6527 0.5 6528 6529 // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter 6530 // Use an explicit zero to avoid NaN (gh-3964) 6531 ) ) || 0; 6532 } 6533 6534 return delta; 6535} 6536 6537function getWidthOrHeight( elem, dimension, extra ) { 6538 6539 // Start with computed style 6540 var styles = getStyles( elem ), 6541 6542 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). 6543 // Fake content-box until we know it's needed to know the true value. 6544 boxSizingNeeded = !support.boxSizingReliable() || extra, 6545 isBorderBox = boxSizingNeeded && 6546 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6547 valueIsBorderBox = isBorderBox, 6548 6549 val = curCSS( elem, dimension, styles ), 6550 offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); 6551 6552 // Support: Firefox <=54 6553 // Return a confounding non-pixel value or feign ignorance, as appropriate. 6554 if ( rnumnonpx.test( val ) ) { 6555 if ( !extra ) { 6556 return val; 6557 } 6558 val = "auto"; 6559 } 6560 6561 6562 // Fall back to offsetWidth/offsetHeight when value is "auto" 6563 // This happens for inline elements with no explicit setting (gh-3571) 6564 // Support: Android <=4.1 - 4.3 only 6565 // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) 6566 // Support: IE 9-11 only 6567 // Also use offsetWidth/offsetHeight for when box sizing is unreliable 6568 // We use getClientRects() to check for hidden/disconnected. 6569 // In those cases, the computed value can be trusted to be border-box 6570 if ( ( !support.boxSizingReliable() && isBorderBox || 6571 val === "auto" || 6572 !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && 6573 elem.getClientRects().length ) { 6574 6575 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 6576 6577 // Where available, offsetWidth/offsetHeight approximate border box dimensions. 6578 // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the 6579 // retrieved value as a content box dimension. 6580 valueIsBorderBox = offsetProp in elem; 6581 if ( valueIsBorderBox ) { 6582 val = elem[ offsetProp ]; 6583 } 6584 } 6585 6586 // Normalize "" and auto 6587 val = parseFloat( val ) || 0; 6588 6589 // Adjust for the element's box model 6590 return ( val + 6591 boxModelAdjustment( 6592 elem, 6593 dimension, 6594 extra || ( isBorderBox ? "border" : "content" ), 6595 valueIsBorderBox, 6596 styles, 6597 6598 // Provide the current computed size to request scroll gutter calculation (gh-3589) 6599 val 6600 ) 6601 ) + "px"; 6602} 6603 6604jQuery.extend( { 6605 6606 // Add in style property hooks for overriding the default 6607 // behavior of getting and setting a style property 6608 cssHooks: { 6609 opacity: { 6610 get: function( elem, computed ) { 6611 if ( computed ) { 6612 6613 // We should always get a number back from opacity 6614 var ret = curCSS( elem, "opacity" ); 6615 return ret === "" ? "1" : ret; 6616 } 6617 } 6618 } 6619 }, 6620 6621 // Don't automatically add "px" to these possibly-unitless properties 6622 cssNumber: { 6623 "animationIterationCount": true, 6624 "columnCount": true, 6625 "fillOpacity": true, 6626 "flexGrow": true, 6627 "flexShrink": true, 6628 "fontWeight": true, 6629 "gridArea": true, 6630 "gridColumn": true, 6631 "gridColumnEnd": true, 6632 "gridColumnStart": true, 6633 "gridRow": true, 6634 "gridRowEnd": true, 6635 "gridRowStart": true, 6636 "lineHeight": true, 6637 "opacity": true, 6638 "order": true, 6639 "orphans": true, 6640 "widows": true, 6641 "zIndex": true, 6642 "zoom": true 6643 }, 6644 6645 // Add in properties whose names you wish to fix before 6646 // setting or getting the value 6647 cssProps: {}, 6648 6649 // Get and set the style property on a DOM Node 6650 style: function( elem, name, value, extra ) { 6651 6652 // Don't set styles on text and comment nodes 6653 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 6654 return; 6655 } 6656 6657 // Make sure that we're working with the right name 6658 var ret, type, hooks, 6659 origName = camelCase( name ), 6660 isCustomProp = rcustomProp.test( name ), 6661 style = elem.style; 6662 6663 // Make sure that we're working with the right name. We don't 6664 // want to query the value if it is a CSS custom property 6665 // since they are user-defined. 6666 if ( !isCustomProp ) { 6667 name = finalPropName( origName ); 6668 } 6669 6670 // Gets hook for the prefixed version, then unprefixed version 6671 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6672 6673 // Check if we're setting a value 6674 if ( value !== undefined ) { 6675 type = typeof value; 6676 6677 // Convert "+=" or "-=" to relative numbers (#7345) 6678 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { 6679 value = adjustCSS( elem, name, ret ); 6680 6681 // Fixes bug #9237 6682 type = "number"; 6683 } 6684 6685 // Make sure that null and NaN values aren't set (#7116) 6686 if ( value == null || value !== value ) { 6687 return; 6688 } 6689 6690 // If a number was passed in, add the unit (except for certain CSS properties) 6691 // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append 6692 // "px" to a few hardcoded values. 6693 if ( type === "number" && !isCustomProp ) { 6694 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); 6695 } 6696 6697 // background-* props affect original clone's values 6698 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { 6699 style[ name ] = "inherit"; 6700 } 6701 6702 // If a hook was provided, use that value, otherwise just set the specified value 6703 if ( !hooks || !( "set" in hooks ) || 6704 ( value = hooks.set( elem, value, extra ) ) !== undefined ) { 6705 6706 if ( isCustomProp ) { 6707 style.setProperty( name, value ); 6708 } else { 6709 style[ name ] = value; 6710 } 6711 } 6712 6713 } else { 6714 6715 // If a hook was provided get the non-computed value from there 6716 if ( hooks && "get" in hooks && 6717 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { 6718 6719 return ret; 6720 } 6721 6722 // Otherwise just get the value from the style object 6723 return style[ name ]; 6724 } 6725 }, 6726 6727 css: function( elem, name, extra, styles ) { 6728 var val, num, hooks, 6729 origName = camelCase( name ), 6730 isCustomProp = rcustomProp.test( name ); 6731 6732 // Make sure that we're working with the right name. We don't 6733 // want to modify the value if it is a CSS custom property 6734 // since they are user-defined. 6735 if ( !isCustomProp ) { 6736 name = finalPropName( origName ); 6737 } 6738 6739 // Try prefixed name followed by the unprefixed name 6740 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6741 6742 // If a hook was provided get the computed value from there 6743 if ( hooks && "get" in hooks ) { 6744 val = hooks.get( elem, true, extra ); 6745 } 6746 6747 // Otherwise, if a way to get the computed value exists, use that 6748 if ( val === undefined ) { 6749 val = curCSS( elem, name, styles ); 6750 } 6751 6752 // Convert "normal" to computed value 6753 if ( val === "normal" && name in cssNormalTransform ) { 6754 val = cssNormalTransform[ name ]; 6755 } 6756 6757 // Make numeric if forced or a qualifier was provided and val looks numeric 6758 if ( extra === "" || extra ) { 6759 num = parseFloat( val ); 6760 return extra === true || isFinite( num ) ? num || 0 : val; 6761 } 6762 6763 return val; 6764 } 6765} ); 6766 6767jQuery.each( [ "height", "width" ], function( i, dimension ) { 6768 jQuery.cssHooks[ dimension ] = { 6769 get: function( elem, computed, extra ) { 6770 if ( computed ) { 6771 6772 // Certain elements can have dimension info if we invisibly show them 6773 // but it must have a current display style that would benefit 6774 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && 6775 6776 // Support: Safari 8+ 6777 // Table columns in Safari have non-zero offsetWidth & zero 6778 // getBoundingClientRect().width unless display is changed. 6779 // Support: IE <=11 only 6780 // Running getBoundingClientRect on a disconnected node 6781 // in IE throws an error. 6782 ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? 6783 swap( elem, cssShow, function() { 6784 return getWidthOrHeight( elem, dimension, extra ); 6785 } ) : 6786 getWidthOrHeight( elem, dimension, extra ); 6787 } 6788 }, 6789 6790 set: function( elem, value, extra ) { 6791 var matches, 6792 styles = getStyles( elem ), 6793 6794 // Only read styles.position if the test has a chance to fail 6795 // to avoid forcing a reflow. 6796 scrollboxSizeBuggy = !support.scrollboxSize() && 6797 styles.position === "absolute", 6798 6799 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) 6800 boxSizingNeeded = scrollboxSizeBuggy || extra, 6801 isBorderBox = boxSizingNeeded && 6802 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6803 subtract = extra ? 6804 boxModelAdjustment( 6805 elem, 6806 dimension, 6807 extra, 6808 isBorderBox, 6809 styles 6810 ) : 6811 0; 6812 6813 // Account for unreliable border-box dimensions by comparing offset* to computed and 6814 // faking a content-box to get border and padding (gh-3699) 6815 if ( isBorderBox && scrollboxSizeBuggy ) { 6816 subtract -= Math.ceil( 6817 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 6818 parseFloat( styles[ dimension ] ) - 6819 boxModelAdjustment( elem, dimension, "border", false, styles ) - 6820 0.5 6821 ); 6822 } 6823 6824 // Convert to pixels if value adjustment is needed 6825 if ( subtract && ( matches = rcssNum.exec( value ) ) && 6826 ( matches[ 3 ] || "px" ) !== "px" ) { 6827 6828 elem.style[ dimension ] = value; 6829 value = jQuery.css( elem, dimension ); 6830 } 6831 6832 return setPositiveNumber( elem, value, subtract ); 6833 } 6834 }; 6835} ); 6836 6837jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, 6838 function( elem, computed ) { 6839 if ( computed ) { 6840 return ( parseFloat( curCSS( elem, "marginLeft" ) ) || 6841 elem.getBoundingClientRect().left - 6842 swap( elem, { marginLeft: 0 }, function() { 6843 return elem.getBoundingClientRect().left; 6844 } ) 6845 ) + "px"; 6846 } 6847 } 6848); 6849 6850// These hooks are used by animate to expand properties 6851jQuery.each( { 6852 margin: "", 6853 padding: "", 6854 border: "Width" 6855}, function( prefix, suffix ) { 6856 jQuery.cssHooks[ prefix + suffix ] = { 6857 expand: function( value ) { 6858 var i = 0, 6859 expanded = {}, 6860 6861 // Assumes a single number if not a string 6862 parts = typeof value === "string" ? value.split( " " ) : [ value ]; 6863 6864 for ( ; i < 4; i++ ) { 6865 expanded[ prefix + cssExpand[ i ] + suffix ] = 6866 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 6867 } 6868 6869 return expanded; 6870 } 6871 }; 6872 6873 if ( prefix !== "margin" ) { 6874 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 6875 } 6876} ); 6877 6878jQuery.fn.extend( { 6879 css: function( name, value ) { 6880 return access( this, function( elem, name, value ) { 6881 var styles, len, 6882 map = {}, 6883 i = 0; 6884 6885 if ( Array.isArray( name ) ) { 6886 styles = getStyles( elem ); 6887 len = name.length; 6888 6889 for ( ; i < len; i++ ) { 6890 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 6891 } 6892 6893 return map; 6894 } 6895 6896 return value !== undefined ? 6897 jQuery.style( elem, name, value ) : 6898 jQuery.css( elem, name ); 6899 }, name, value, arguments.length > 1 ); 6900 } 6901} ); 6902 6903 6904function Tween( elem, options, prop, end, easing ) { 6905 return new Tween.prototype.init( elem, options, prop, end, easing ); 6906} 6907jQuery.Tween = Tween; 6908 6909Tween.prototype = { 6910 constructor: Tween, 6911 init: function( elem, options, prop, end, easing, unit ) { 6912 this.elem = elem; 6913 this.prop = prop; 6914 this.easing = easing || jQuery.easing._default; 6915 this.options = options; 6916 this.start = this.now = this.cur(); 6917 this.end = end; 6918 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 6919 }, 6920 cur: function() { 6921 var hooks = Tween.propHooks[ this.prop ]; 6922 6923 return hooks && hooks.get ? 6924 hooks.get( this ) : 6925 Tween.propHooks._default.get( this ); 6926 }, 6927 run: function( percent ) { 6928 var eased, 6929 hooks = Tween.propHooks[ this.prop ]; 6930 6931 if ( this.options.duration ) { 6932 this.pos = eased = jQuery.easing[ this.easing ]( 6933 percent, this.options.duration * percent, 0, 1, this.options.duration 6934 ); 6935 } else { 6936 this.pos = eased = percent; 6937 } 6938 this.now = ( this.end - this.start ) * eased + this.start; 6939 6940 if ( this.options.step ) { 6941 this.options.step.call( this.elem, this.now, this ); 6942 } 6943 6944 if ( hooks && hooks.set ) { 6945 hooks.set( this ); 6946 } else { 6947 Tween.propHooks._default.set( this ); 6948 } 6949 return this; 6950 } 6951}; 6952 6953Tween.prototype.init.prototype = Tween.prototype; 6954 6955Tween.propHooks = { 6956 _default: { 6957 get: function( tween ) { 6958 var result; 6959 6960 // Use a property on the element directly when it is not a DOM element, 6961 // or when there is no matching style property that exists. 6962 if ( tween.elem.nodeType !== 1 || 6963 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { 6964 return tween.elem[ tween.prop ]; 6965 } 6966 6967 // Passing an empty string as a 3rd parameter to .css will automatically 6968 // attempt a parseFloat and fallback to a string if the parse fails. 6969 // Simple values such as "10px" are parsed to Float; 6970 // complex values such as "rotate(1rad)" are returned as-is. 6971 result = jQuery.css( tween.elem, tween.prop, "" ); 6972 6973 // Empty strings, null, undefined and "auto" are converted to 0. 6974 return !result || result === "auto" ? 0 : result; 6975 }, 6976 set: function( tween ) { 6977 6978 // Use step hook for back compat. 6979 // Use cssHook if its there. 6980 // Use .style if available and use plain properties where available. 6981 if ( jQuery.fx.step[ tween.prop ] ) { 6982 jQuery.fx.step[ tween.prop ]( tween ); 6983 } else if ( tween.elem.nodeType === 1 && ( 6984 jQuery.cssHooks[ tween.prop ] || 6985 tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { 6986 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 6987 } else { 6988 tween.elem[ tween.prop ] = tween.now; 6989 } 6990 } 6991 } 6992}; 6993 6994// Support: IE <=9 only 6995// Panic based approach to setting things on disconnected nodes 6996Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 6997 set: function( tween ) { 6998 if ( tween.elem.nodeType && tween.elem.parentNode ) { 6999 tween.elem[ tween.prop ] = tween.now; 7000 } 7001 } 7002}; 7003 7004jQuery.easing = { 7005 linear: function( p ) { 7006 return p; 7007 }, 7008 swing: function( p ) { 7009 return 0.5 - Math.cos( p * Math.PI ) / 2; 7010 }, 7011 _default: "swing" 7012}; 7013 7014jQuery.fx = Tween.prototype.init; 7015 7016// Back compat <1.8 extension point 7017jQuery.fx.step = {}; 7018 7019 7020 7021 7022var 7023 fxNow, inProgress, 7024 rfxtypes = /^(?:toggle|show|hide)$/, 7025 rrun = /queueHooks$/; 7026 7027function schedule() { 7028 if ( inProgress ) { 7029 if ( document.hidden === false && window.requestAnimationFrame ) { 7030 window.requestAnimationFrame( schedule ); 7031 } else { 7032 window.setTimeout( schedule, jQuery.fx.interval ); 7033 } 7034 7035 jQuery.fx.tick(); 7036 } 7037} 7038 7039// Animations created synchronously will run synchronously 7040function createFxNow() { 7041 window.setTimeout( function() { 7042 fxNow = undefined; 7043 } ); 7044 return ( fxNow = Date.now() ); 7045} 7046 7047// Generate parameters to create a standard animation 7048function genFx( type, includeWidth ) { 7049 var which, 7050 i = 0, 7051 attrs = { height: type }; 7052 7053 // If we include width, step value is 1 to do all cssExpand values, 7054 // otherwise step value is 2 to skip over Left and Right 7055 includeWidth = includeWidth ? 1 : 0; 7056 for ( ; i < 4; i += 2 - includeWidth ) { 7057 which = cssExpand[ i ]; 7058 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 7059 } 7060 7061 if ( includeWidth ) { 7062 attrs.opacity = attrs.width = type; 7063 } 7064 7065 return attrs; 7066} 7067 7068function createTween( value, prop, animation ) { 7069 var tween, 7070 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), 7071 index = 0, 7072 length = collection.length; 7073 for ( ; index < length; index++ ) { 7074 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { 7075 7076 // We're done with this property 7077 return tween; 7078 } 7079 } 7080} 7081 7082function defaultPrefilter( elem, props, opts ) { 7083 var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, 7084 isBox = "width" in props || "height" in props, 7085 anim = this, 7086 orig = {}, 7087 style = elem.style, 7088 hidden = elem.nodeType && isHiddenWithinTree( elem ), 7089 dataShow = dataPriv.get( elem, "fxshow" ); 7090 7091 // Queue-skipping animations hijack the fx hooks 7092 if ( !opts.queue ) { 7093 hooks = jQuery._queueHooks( elem, "fx" ); 7094 if ( hooks.unqueued == null ) { 7095 hooks.unqueued = 0; 7096 oldfire = hooks.empty.fire; 7097 hooks.empty.fire = function() { 7098 if ( !hooks.unqueued ) { 7099 oldfire(); 7100 } 7101 }; 7102 } 7103 hooks.unqueued++; 7104 7105 anim.always( function() { 7106 7107 // Ensure the complete handler is called before this completes 7108 anim.always( function() { 7109 hooks.unqueued--; 7110 if ( !jQuery.queue( elem, "fx" ).length ) { 7111 hooks.empty.fire(); 7112 } 7113 } ); 7114 } ); 7115 } 7116 7117 // Detect show/hide animations 7118 for ( prop in props ) { 7119 value = props[ prop ]; 7120 if ( rfxtypes.test( value ) ) { 7121 delete props[ prop ]; 7122 toggle = toggle || value === "toggle"; 7123 if ( value === ( hidden ? "hide" : "show" ) ) { 7124 7125 // Pretend to be hidden if this is a "show" and 7126 // there is still data from a stopped show/hide 7127 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 7128 hidden = true; 7129 7130 // Ignore all other no-op show/hide data 7131 } else { 7132 continue; 7133 } 7134 } 7135 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 7136 } 7137 } 7138 7139 // Bail out if this is a no-op like .hide().hide() 7140 propTween = !jQuery.isEmptyObject( props ); 7141 if ( !propTween && jQuery.isEmptyObject( orig ) ) { 7142 return; 7143 } 7144 7145 // Restrict "overflow" and "display" styles during box animations 7146 if ( isBox && elem.nodeType === 1 ) { 7147
vendor: 4,220 bytes, lines 7148-7307
7148 // Support: IE <=9 - 11, Edge 12 - 15 7149 // Record all 3 overflow attributes because IE does not infer the shorthand 7150 // from identically-valued overflowX and overflowY and Edge just mirrors 7151 // the overflowX value there. 7152 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 7153 7154 // Identify a display type, preferring old show/hide data over the CSS cascade 7155 restoreDisplay = dataShow && dataShow.display; 7156 if ( restoreDisplay == null ) { 7157 restoreDisplay = dataPriv.get( elem, "display" ); 7158 } 7159 display = jQuery.css( elem, "display" ); 7160 if ( display === "none" ) { 7161 if ( restoreDisplay ) { 7162 display = restoreDisplay; 7163 } else { 7164 7165 // Get nonempty value(s) by temporarily forcing visibility 7166 showHide( [ elem ], true ); 7167 restoreDisplay = elem.style.display || restoreDisplay; 7168 display = jQuery.css( elem, "display" ); 7169 showHide( [ elem ] ); 7170 } 7171 } 7172 7173 // Animate inline elements as inline-block 7174 if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { 7175 if ( jQuery.css( elem, "float" ) === "none" ) { 7176 7177 // Restore the original display value at the end of pure show/hide animations 7178 if ( !propTween ) { 7179 anim.done( function() { 7180 style.display = restoreDisplay; 7181 } ); 7182 if ( restoreDisplay == null ) { 7183 display = style.display; 7184 restoreDisplay = display === "none" ? "" : display; 7185 } 7186 } 7187 style.display = "inline-block"; 7188 } 7189 } 7190 } 7191 7192 if ( opts.overflow ) { 7193 style.overflow = "hidden"; 7194 anim.always( function() { 7195 style.overflow = opts.overflow[ 0 ]; 7196 style.overflowX = opts.overflow[ 1 ]; 7197 style.overflowY = opts.overflow[ 2 ]; 7198 } ); 7199 } 7200 7201 // Implement show/hide animations 7202 propTween = false; 7203 for ( prop in orig ) { 7204 7205 // General show/hide setup for this element animation 7206 if ( !propTween ) { 7207 if ( dataShow ) { 7208 if ( "hidden" in dataShow ) { 7209 hidden = dataShow.hidden; 7210 } 7211 } else { 7212 dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); 7213 } 7214 7215 // Store hidden/visible for toggle so `.stop().toggle()` "reverses" 7216 if ( toggle ) { 7217 dataShow.hidden = !hidden; 7218 } 7219 7220 // Show elements before animating them 7221 if ( hidden ) { 7222 showHide( [ elem ], true ); 7223 } 7224 7225 /* eslint-disable no-loop-func */ 7226 7227 anim.done( function() { 7228 7229 /* eslint-enable no-loop-func */ 7230 7231 // The final step of a "hide" animation is actually hiding the element 7232 if ( !hidden ) { 7233 showHide( [ elem ] ); 7234 } 7235 dataPriv.remove( elem, "fxshow" ); 7236 for ( prop in orig ) { 7237 jQuery.style( elem, prop, orig[ prop ] ); 7238 } 7239 } ); 7240 } 7241 7242 // Per-property setup 7243 propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 7244 if ( !( prop in dataShow ) ) { 7245 dataShow[ prop ] = propTween.start; 7246 if ( hidden ) { 7247 propTween.end = propTween.start; 7248 propTween.start = 0; 7249 } 7250 } 7251 } 7252} 7253 7254function propFilter( props, specialEasing ) { 7255 var index, name, easing, value, hooks; 7256 7257 // camelCase, specialEasing and expand cssHook pass 7258 for ( index in props ) { 7259 name = camelCase( index ); 7260 easing = specialEasing[ name ]; 7261 value = props[ index ]; 7262 if ( Array.isArray( value ) ) { 7263 easing = value[ 1 ]; 7264 value = props[ index ] = value[ 0 ]; 7265 } 7266 7267 if ( index !== name ) { 7268 props[ name ] = value; 7269 delete props[ index ]; 7270 } 7271 7272 hooks = jQuery.cssHooks[ name ]; 7273 if ( hooks && "expand" in hooks ) { 7274 value = hooks.expand( value ); 7275 delete props[ name ]; 7276 7277 // Not quite $.extend, this won't overwrite existing keys. 7278 // Reusing 'index' because we have the correct "name" 7279 for ( index in value ) { 7280 if ( !( index in props ) ) { 7281 props[ index ] = value[ index ]; 7282 specialEasing[ index ] = easing; 7283 } 7284 } 7285 } else { 7286 specialEasing[ name ] = easing; 7287 } 7288 } 7289} 7290 7291function Animation( elem, properties, options ) { 7292 var result, 7293 stopped, 7294 index = 0, 7295 length = Animation.prefilters.length, 7296 deferred = jQuery.Deferred().always( function() { 7297 7298 // Don't match elem in the :animated selector 7299 delete tick.elem; 7300 } ), 7301 tick = function() { 7302 if ( stopped ) { 7303 return false; 7304 } 7305 var currentTime = fxNow || createFxNow(), 7306 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 7307
vendor: 20,984 bytes, lines 7308-8178
7308 // Support: Android 2.3 only 7309 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) 7310 temp = remaining / animation.duration || 0, 7311 percent = 1 - temp, 7312 index = 0, 7313 length = animation.tweens.length; 7314 7315 for ( ; index < length; index++ ) { 7316 animation.tweens[ index ].run( percent ); 7317 } 7318 7319 deferred.notifyWith( elem, [ animation, percent, remaining ] ); 7320 7321 // If there's more to do, yield 7322 if ( percent < 1 && length ) { 7323 return remaining; 7324 } 7325 7326 // If this was an empty animation, synthesize a final progress notification 7327 if ( !length ) { 7328 deferred.notifyWith( elem, [ animation, 1, 0 ] ); 7329 } 7330 7331 // Resolve the animation and report its conclusion 7332 deferred.resolveWith( elem, [ animation ] ); 7333 return false; 7334 }, 7335 animation = deferred.promise( { 7336 elem: elem, 7337 props: jQuery.extend( {}, properties ), 7338 opts: jQuery.extend( true, { 7339 specialEasing: {}, 7340 easing: jQuery.easing._default 7341 }, options ), 7342 originalProperties: properties, 7343 originalOptions: options, 7344 startTime: fxNow || createFxNow(), 7345 duration: options.duration, 7346 tweens: [], 7347 createTween: function( prop, end ) { 7348 var tween = jQuery.Tween( elem, animation.opts, prop, end, 7349 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 7350 animation.tweens.push( tween ); 7351 return tween; 7352 }, 7353 stop: function( gotoEnd ) { 7354 var index = 0, 7355 7356 // If we are going to the end, we want to run all the tweens 7357 // otherwise we skip this part 7358 length = gotoEnd ? animation.tweens.length : 0; 7359 if ( stopped ) { 7360 return this; 7361 } 7362 stopped = true; 7363 for ( ; index < length; index++ ) { 7364 animation.tweens[ index ].run( 1 ); 7365 } 7366 7367 // Resolve when we played the last frame; otherwise, reject 7368 if ( gotoEnd ) { 7369 deferred.notifyWith( elem, [ animation, 1, 0 ] ); 7370 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 7371 } else { 7372 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 7373 } 7374 return this; 7375 } 7376 } ), 7377 props = animation.props; 7378 7379 propFilter( props, animation.opts.specialEasing ); 7380 7381 for ( ; index < length; index++ ) { 7382 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); 7383 if ( result ) { 7384 if ( isFunction( result.stop ) ) { 7385 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = 7386 result.stop.bind( result ); 7387 } 7388 return result; 7389 } 7390 } 7391 7392 jQuery.map( props, createTween, animation ); 7393 7394 if ( isFunction( animation.opts.start ) ) { 7395 animation.opts.start.call( elem, animation ); 7396 } 7397 7398 // Attach callbacks from options 7399 animation 7400 .progress( animation.opts.progress ) 7401 .done( animation.opts.done, animation.opts.complete ) 7402 .fail( animation.opts.fail ) 7403 .always( animation.opts.always ); 7404 7405 jQuery.fx.timer( 7406 jQuery.extend( tick, { 7407 elem: elem, 7408 anim: animation, 7409 queue: animation.opts.queue 7410 } ) 7411 ); 7412 7413 return animation; 7414} 7415 7416jQuery.Animation = jQuery.extend( Animation, { 7417 7418 tweeners: { 7419 "*": [ function( prop, value ) { 7420 var tween = this.createTween( prop, value ); 7421 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); 7422 return tween; 7423 } ] 7424 }, 7425 7426 tweener: function( props, callback ) { 7427 if ( isFunction( props ) ) { 7428 callback = props; 7429 props = [ "*" ]; 7430 } else { 7431 props = props.match( rnothtmlwhite ); 7432 } 7433 7434 var prop, 7435 index = 0, 7436 length = props.length; 7437 7438 for ( ; index < length; index++ ) { 7439 prop = props[ index ]; 7440 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; 7441 Animation.tweeners[ prop ].unshift( callback ); 7442 } 7443 }, 7444 7445 prefilters: [ defaultPrefilter ], 7446 7447 prefilter: function( callback, prepend ) { 7448 if ( prepend ) { 7449 Animation.prefilters.unshift( callback ); 7450 } else { 7451 Animation.prefilters.push( callback ); 7452 } 7453 } 7454} ); 7455 7456jQuery.speed = function( speed, easing, fn ) { 7457 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 7458 complete: fn || !fn && easing || 7459 isFunction( speed ) && speed, 7460 duration: speed, 7461 easing: fn && easing || easing && !isFunction( easing ) && easing 7462 }; 7463 7464 // Go to the end state if fx are off 7465 if ( jQuery.fx.off ) { 7466 opt.duration = 0; 7467 7468 } else { 7469 if ( typeof opt.duration !== "number" ) { 7470 if ( opt.duration in jQuery.fx.speeds ) { 7471 opt.duration = jQuery.fx.speeds[ opt.duration ]; 7472 7473 } else { 7474 opt.duration = jQuery.fx.speeds._default; 7475 } 7476 } 7477 } 7478 7479 // Normalize opt.queue - true/undefined/null -> "fx" 7480 if ( opt.queue == null || opt.queue === true ) { 7481 opt.queue = "fx"; 7482 } 7483 7484 // Queueing 7485 opt.old = opt.complete; 7486 7487 opt.complete = function() { 7488 if ( isFunction( opt.old ) ) { 7489 opt.old.call( this ); 7490 } 7491 7492 if ( opt.queue ) { 7493 jQuery.dequeue( this, opt.queue ); 7494 } 7495 }; 7496 7497 return opt; 7498}; 7499 7500jQuery.fn.extend( { 7501 fadeTo: function( speed, to, easing, callback ) { 7502 7503 // Show any hidden elements after setting opacity to 0 7504 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() 7505 7506 // Animate to the value specified 7507 .end().animate( { opacity: to }, speed, easing, callback ); 7508 }, 7509 animate: function( prop, speed, easing, callback ) { 7510 var empty = jQuery.isEmptyObject( prop ), 7511 optall = jQuery.speed( speed, easing, callback ), 7512 doAnimation = function() { 7513 7514 // Operate on a copy of prop so per-property easing won't be lost 7515 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 7516 7517 // Empty animations, or finishing resolves immediately 7518 if ( empty || dataPriv.get( this, "finish" ) ) { 7519 anim.stop( true ); 7520 } 7521 }; 7522 doAnimation.finish = doAnimation; 7523 7524 return empty || optall.queue === false ? 7525 this.each( doAnimation ) : 7526 this.queue( optall.queue, doAnimation ); 7527 }, 7528 stop: function( type, clearQueue, gotoEnd ) { 7529 var stopQueue = function( hooks ) { 7530 var stop = hooks.stop; 7531 delete hooks.stop; 7532 stop( gotoEnd ); 7533 }; 7534 7535 if ( typeof type !== "string" ) { 7536 gotoEnd = clearQueue; 7537 clearQueue = type; 7538 type = undefined; 7539 } 7540 if ( clearQueue && type !== false ) { 7541 this.queue( type || "fx", [] ); 7542 } 7543 7544 return this.each( function() { 7545 var dequeue = true, 7546 index = type != null && type + "queueHooks", 7547 timers = jQuery.timers, 7548 data = dataPriv.get( this ); 7549 7550 if ( index ) { 7551 if ( data[ index ] && data[ index ].stop ) { 7552 stopQueue( data[ index ] ); 7553 } 7554 } else { 7555 for ( index in data ) { 7556 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 7557 stopQueue( data[ index ] ); 7558 } 7559 } 7560 } 7561 7562 for ( index = timers.length; index--; ) { 7563 if ( timers[ index ].elem === this && 7564 ( type == null || timers[ index ].queue === type ) ) { 7565 7566 timers[ index ].anim.stop( gotoEnd ); 7567 dequeue = false; 7568 timers.splice( index, 1 ); 7569 } 7570 } 7571 7572 // Start the next in the queue if the last step wasn't forced. 7573 // Timers currently will call their complete callbacks, which 7574 // will dequeue but only if they were gotoEnd. 7575 if ( dequeue || !gotoEnd ) { 7576 jQuery.dequeue( this, type ); 7577 } 7578 } ); 7579 }, 7580 finish: function( type ) { 7581 if ( type !== false ) { 7582 type = type || "fx"; 7583 } 7584 return this.each( function() { 7585 var index, 7586 data = dataPriv.get( this ), 7587 queue = data[ type + "queue" ], 7588 hooks = data[ type + "queueHooks" ], 7589 timers = jQuery.timers, 7590 length = queue ? queue.length : 0; 7591 7592 // Enable finishing flag on private data 7593 data.finish = true; 7594 7595 // Empty the queue first 7596 jQuery.queue( this, type, [] ); 7597 7598 if ( hooks && hooks.stop ) { 7599 hooks.stop.call( this, true ); 7600 } 7601 7602 // Look for any active animations, and finish them 7603 for ( index = timers.length; index--; ) { 7604 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 7605 timers[ index ].anim.stop( true ); 7606 timers.splice( index, 1 ); 7607 } 7608 } 7609 7610 // Look for any animations in the old queue and finish them 7611 for ( index = 0; index < length; index++ ) { 7612 if ( queue[ index ] && queue[ index ].finish ) { 7613 queue[ index ].finish.call( this ); 7614 } 7615 } 7616 7617 // Turn off finishing flag 7618 delete data.finish; 7619 } ); 7620 } 7621} ); 7622 7623jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { 7624 var cssFn = jQuery.fn[ name ]; 7625 jQuery.fn[ name ] = function( speed, easing, callback ) { 7626 return speed == null || typeof speed === "boolean" ? 7627 cssFn.apply( this, arguments ) : 7628 this.animate( genFx( name, true ), speed, easing, callback ); 7629 }; 7630} ); 7631 7632// Generate shortcuts for custom animations 7633jQuery.each( { 7634 slideDown: genFx( "show" ), 7635 slideUp: genFx( "hide" ), 7636 slideToggle: genFx( "toggle" ), 7637 fadeIn: { opacity: "show" }, 7638 fadeOut: { opacity: "hide" }, 7639 fadeToggle: { opacity: "toggle" } 7640}, function( name, props ) { 7641 jQuery.fn[ name ] = function( speed, easing, callback ) { 7642 return this.animate( props, speed, easing, callback ); 7643 }; 7644} ); 7645 7646jQuery.timers = []; 7647jQuery.fx.tick = function() { 7648 var timer, 7649 i = 0, 7650 timers = jQuery.timers; 7651 7652 fxNow = Date.now(); 7653 7654 for ( ; i < timers.length; i++ ) { 7655 timer = timers[ i ]; 7656 7657 // Run the timer and safely remove it when done (allowing for external removal) 7658 if ( !timer() && timers[ i ] === timer ) { 7659 timers.splice( i--, 1 ); 7660 } 7661 } 7662 7663 if ( !timers.length ) { 7664 jQuery.fx.stop(); 7665 } 7666 fxNow = undefined; 7667}; 7668 7669jQuery.fx.timer = function( timer ) { 7670 jQuery.timers.push( timer ); 7671 jQuery.fx.start(); 7672}; 7673 7674jQuery.fx.interval = 13; 7675jQuery.fx.start = function() { 7676 if ( inProgress ) { 7677 return; 7678 } 7679 7680 inProgress = true; 7681 schedule(); 7682}; 7683 7684jQuery.fx.stop = function() { 7685 inProgress = null; 7686}; 7687 7688jQuery.fx.speeds = { 7689 slow: 600, 7690 fast: 200, 7691 7692 // Default speed 7693 _default: 400 7694}; 7695 7696 7697// Based off of the plugin by Clint Helfers, with permission. 7698// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ 7699jQuery.fn.delay = function( time, type ) { 7700 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 7701 type = type || "fx"; 7702 7703 return this.queue( type, function( next, hooks ) { 7704 var timeout = window.setTimeout( next, time ); 7705 hooks.stop = function() { 7706 window.clearTimeout( timeout ); 7707 }; 7708 } ); 7709}; 7710 7711 7712( function() { 7713 var input = document.createElement( "input" ), 7714 select = document.createElement( "select" ), 7715 opt = select.appendChild( document.createElement( "option" ) ); 7716 7717 input.type = "checkbox"; 7718 7719 // Support: Android <=4.3 only 7720 // Default value for a checkbox should be "on" 7721 support.checkOn = input.value !== ""; 7722 7723 // Support: IE <=11 only 7724 // Must access selectedIndex to make default options select 7725 support.optSelected = opt.selected; 7726 7727 // Support: IE <=11 only 7728 // An input loses its value after becoming a radio 7729 input = document.createElement( "input" ); 7730 input.value = "t"; 7731 input.type = "radio"; 7732 support.radioValue = input.value === "t"; 7733} )(); 7734 7735 7736var boolHook, 7737 attrHandle = jQuery.expr.attrHandle; 7738 7739jQuery.fn.extend( { 7740 attr: function( name, value ) { 7741 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 7742 }, 7743 7744 removeAttr: function( name ) { 7745 return this.each( function() { 7746 jQuery.removeAttr( this, name ); 7747 } ); 7748 } 7749} ); 7750 7751jQuery.extend( { 7752 attr: function( elem, name, value ) { 7753 var ret, hooks, 7754 nType = elem.nodeType; 7755 7756 // Don't get/set attributes on text, comment and attribute nodes 7757 if ( nType === 3 || nType === 8 || nType === 2 ) { 7758 return; 7759 } 7760 7761 // Fallback to prop when attributes are not supported 7762 if ( typeof elem.getAttribute === "undefined" ) { 7763 return jQuery.prop( elem, name, value ); 7764 } 7765 7766 // Attribute hooks are determined by the lowercase version 7767 // Grab necessary hook if one is defined 7768 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7769 hooks = jQuery.attrHooks[ name.toLowerCase() ] || 7770 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); 7771 } 7772 7773 if ( value !== undefined ) { 7774 if ( value === null ) { 7775 jQuery.removeAttr( elem, name ); 7776 return; 7777 } 7778 7779 if ( hooks && "set" in hooks && 7780 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 7781 return ret; 7782 } 7783 7784 elem.setAttribute( name, value + "" ); 7785 return value; 7786 } 7787 7788 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 7789 return ret; 7790 } 7791 7792 ret = jQuery.find.attr( elem, name ); 7793 7794 // Non-existent attributes return null, we normalize to undefined 7795 return ret == null ? undefined : ret; 7796 }, 7797 7798 attrHooks: { 7799 type: { 7800 set: function( elem, value ) { 7801 if ( !support.radioValue && value === "radio" && 7802 nodeName( elem, "input" ) ) { 7803 var val = elem.value; 7804 elem.setAttribute( "type", value ); 7805 if ( val ) { 7806 elem.value = val; 7807 } 7808 return value; 7809 } 7810 } 7811 } 7812 }, 7813 7814 removeAttr: function( elem, value ) { 7815 var name, 7816 i = 0, 7817 7818 // Attribute names can contain non-HTML whitespace characters 7819 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 7820 attrNames = value && value.match( rnothtmlwhite ); 7821 7822 if ( attrNames && elem.nodeType === 1 ) { 7823 while ( ( name = attrNames[ i++ ] ) ) { 7824 elem.removeAttribute( name ); 7825 } 7826 } 7827 } 7828} ); 7829 7830// Hooks for boolean attributes 7831boolHook = { 7832 set: function( elem, value, name ) { 7833 if ( value === false ) { 7834 7835 // Remove boolean attributes when set to false 7836 jQuery.removeAttr( elem, name ); 7837 } else { 7838 elem.setAttribute( name, name ); 7839 } 7840 return name; 7841 } 7842}; 7843 7844jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { 7845 var getter = attrHandle[ name ] || jQuery.find.attr; 7846 7847 attrHandle[ name ] = function( elem, name, isXML ) { 7848 var ret, handle, 7849 lowercaseName = name.toLowerCase(); 7850 7851 if ( !isXML ) { 7852 7853 // Avoid an infinite loop by temporarily removing this function from the getter 7854 handle = attrHandle[ lowercaseName ]; 7855 attrHandle[ lowercaseName ] = ret; 7856 ret = getter( elem, name, isXML ) != null ? 7857 lowercaseName : 7858 null; 7859 attrHandle[ lowercaseName ] = handle; 7860 } 7861 return ret; 7862 }; 7863} ); 7864 7865 7866 7867 7868var rfocusable = /^(?:input|select|textarea|button)$/i, 7869 rclickable = /^(?:a|area)$/i; 7870 7871jQuery.fn.extend( { 7872 prop: function( name, value ) { 7873 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 7874 }, 7875 7876 removeProp: function( name ) { 7877 return this.each( function() { 7878 delete this[ jQuery.propFix[ name ] || name ]; 7879 } ); 7880 } 7881} ); 7882 7883jQuery.extend( { 7884 prop: function( elem, name, value ) { 7885 var ret, hooks, 7886 nType = elem.nodeType; 7887 7888 // Don't get/set properties on text, comment and attribute nodes 7889 if ( nType === 3 || nType === 8 || nType === 2 ) { 7890 return; 7891 } 7892 7893 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7894 7895 // Fix name and attach hooks 7896 name = jQuery.propFix[ name ] || name; 7897 hooks = jQuery.propHooks[ name ]; 7898 } 7899 7900 if ( value !== undefined ) { 7901 if ( hooks && "set" in hooks && 7902 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 7903 return ret; 7904 } 7905 7906 return ( elem[ name ] = value ); 7907 } 7908 7909 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 7910 return ret; 7911 } 7912 7913 return elem[ name ]; 7914 }, 7915 7916 propHooks: { 7917 tabIndex: { 7918 get: function( elem ) { 7919 7920 // Support: IE <=9 - 11 only 7921 // elem.tabIndex doesn't always return the 7922 // correct value when it hasn't been explicitly set 7923 // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 7924 // Use proper attribute retrieval(#12072) 7925 var tabindex = jQuery.find.attr( elem, "tabindex" ); 7926 7927 if ( tabindex ) { 7928 return parseInt( tabindex, 10 ); 7929 } 7930 7931 if ( 7932 rfocusable.test( elem.nodeName ) || 7933 rclickable.test( elem.nodeName ) && 7934 elem.href 7935 ) { 7936 return 0; 7937 } 7938 7939 return -1; 7940 } 7941 } 7942 }, 7943 7944 propFix: { 7945 "for": "htmlFor", 7946 "class": "className" 7947 } 7948} ); 7949 7950// Support: IE <=11 only 7951// Accessing the selectedIndex property 7952// forces the browser to respect setting selected 7953// on the option 7954// The getter ensures a default option is selected 7955// when in an optgroup 7956// eslint rule "no-unused-expressions" is disabled for this code 7957// since it considers such accessions noop 7958if ( !support.optSelected ) { 7959 jQuery.propHooks.selected = { 7960 get: function( elem ) { 7961 7962 /* eslint no-unused-expressions: "off" */ 7963 7964 var parent = elem.parentNode; 7965 if ( parent && parent.parentNode ) { 7966 parent.parentNode.selectedIndex; 7967 } 7968 return null; 7969 }, 7970 set: function( elem ) { 7971 7972 /* eslint no-unused-expressions: "off" */ 7973 7974 var parent = elem.parentNode; 7975 if ( parent ) { 7976 parent.selectedIndex; 7977 7978 if ( parent.parentNode ) { 7979 parent.parentNode.selectedIndex; 7980 } 7981 } 7982 } 7983 }; 7984} 7985 7986jQuery.each( [ 7987 "tabIndex", 7988 "readOnly", 7989 "maxLength", 7990 "cellSpacing", 7991 "cellPadding", 7992 "rowSpan", 7993 "colSpan", 7994 "useMap", 7995 "frameBorder", 7996 "contentEditable" 7997], function() { 7998 jQuery.propFix[ this.toLowerCase() ] = this; 7999} ); 8000 8001 8002 8003 8004 // Strip and collapse whitespace according to HTML spec 8005 // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace 8006 function stripAndCollapse( value ) { 8007 var tokens = value.match( rnothtmlwhite ) || []; 8008 return tokens.join( " " ); 8009 } 8010 8011 8012function getClass( elem ) { 8013 return elem.getAttribute && elem.getAttribute( "class" ) || ""; 8014} 8015 8016function classesToArray( value ) { 8017 if ( Array.isArray( value ) ) { 8018 return value; 8019 } 8020 if ( typeof value === "string" ) { 8021 return value.match( rnothtmlwhite ) || []; 8022 } 8023 return []; 8024} 8025 8026jQuery.fn.extend( { 8027 addClass: function( value ) { 8028 var classes, elem, cur, curValue, clazz, j, finalValue, 8029 i = 0; 8030 8031 if ( isFunction( value ) ) { 8032 return this.each( function( j ) { 8033 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); 8034 } ); 8035 } 8036 8037 classes = classesToArray( value ); 8038 8039 if ( classes.length ) { 8040 while ( ( elem = this[ i++ ] ) ) { 8041 curValue = getClass( elem ); 8042 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); 8043 8044 if ( cur ) { 8045 j = 0; 8046 while ( ( clazz = classes[ j++ ] ) ) { 8047 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 8048 cur += clazz + " "; 8049 } 8050 } 8051 8052 // Only assign if different to avoid unneeded rendering. 8053 finalValue = stripAndCollapse( cur ); 8054 if ( curValue !== finalValue ) { 8055 elem.setAttribute( "class", finalValue ); 8056 } 8057 } 8058 } 8059 } 8060 8061 return this; 8062 }, 8063 8064 removeClass: function( value ) { 8065 var classes, elem, cur, curValue, clazz, j, finalValue, 8066 i = 0; 8067 8068 if ( isFunction( value ) ) { 8069 return this.each( function( j ) { 8070 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); 8071 } ); 8072 } 8073 8074 if ( !arguments.length ) { 8075 return this.attr( "class", "" ); 8076 } 8077 8078 classes = classesToArray( value ); 8079 8080 if ( classes.length ) { 8081 while ( ( elem = this[ i++ ] ) ) { 8082 curValue = getClass( elem ); 8083 8084 // This expression is here for better compressibility (see addClass) 8085 cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); 8086 8087 if ( cur ) { 8088 j = 0; 8089 while ( ( clazz = classes[ j++ ] ) ) { 8090 8091 // Remove *all* instances 8092 while ( cur.indexOf( " " + clazz + " " ) > -1 ) { 8093 cur = cur.replace( " " + clazz + " ", " " ); 8094 } 8095 } 8096 8097 // Only assign if different to avoid unneeded rendering. 8098 finalValue = stripAndCollapse( cur ); 8099 if ( curValue !== finalValue ) { 8100 elem.setAttribute( "class", finalValue ); 8101 } 8102 } 8103 } 8104 } 8105 8106 return this; 8107 }, 8108 8109 toggleClass: function( value, stateVal ) { 8110 var type = typeof value, 8111 isValidValue = type === "string" || Array.isArray( value ); 8112 8113 if ( typeof stateVal === "boolean" && isValidValue ) { 8114 return stateVal ? this.addClass( value ) : this.removeClass( value ); 8115 } 8116 8117 if ( isFunction( value ) ) { 8118 return this.each( function( i ) { 8119 jQuery( this ).toggleClass( 8120 value.call( this, i, getClass( this ), stateVal ), 8121 stateVal 8122 ); 8123 } ); 8124 } 8125 8126 return this.each( function() { 8127 var className, i, self, classNames; 8128 8129 if ( isValidValue ) { 8130 8131 // Toggle individual class names 8132 i = 0; 8133 self = jQuery( this ); 8134 classNames = classesToArray( value ); 8135 8136 while ( ( className = classNames[ i++ ] ) ) { 8137 8138 // Check each className given, space separated list 8139 if ( self.hasClass( className ) ) { 8140 self.removeClass( className ); 8141 } else { 8142 self.addClass( className ); 8143 } 8144 } 8145 8146 // Toggle whole class name 8147 } else if ( value === undefined || type === "boolean" ) { 8148 className = getClass( this ); 8149 if ( className ) { 8150 8151 // Store className if set 8152 dataPriv.set( this, "__className__", className ); 8153 } 8154 8155 // If the element has a class name or if we're passed `false`, 8156 // then remove the whole classname (if there was one, the above saved it). 8157 // Otherwise bring back whatever was previously saved (if anything), 8158 // falling back to the empty string if nothing was stored. 8159 if ( this.setAttribute ) { 8160 this.setAttribute( "class", 8161 className || value === false ? 8162 "" : 8163 dataPriv.get( this, "__className__" ) || "" 8164 ); 8165 } 8166 } 8167 } ); 8168 }, 8169 8170 hasClass: function( selector ) { 8171 var className, elem, 8172 i = 0; 8173 8174 className = " " + selector + " "; 8175 while ( ( elem = this[ i++ ] ) ) { 8176 if ( elem.nodeType === 1 && 8177 ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { 8178
vendor: 1,792 bytes, lines 8178-8270
8178 return true; 8179 } 8180 } 8181 8182 return false; 8183 } 8184} ); 8185 8186 8187 8188 8189var rreturn = /\r/g; 8190 8191jQuery.fn.extend( { 8192 val: function( value ) { 8193 var hooks, ret, valueIsFunction, 8194 elem = this[ 0 ]; 8195 8196 if ( !arguments.length ) { 8197 if ( elem ) { 8198 hooks = jQuery.valHooks[ elem.type ] || 8199 jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 8200 8201 if ( hooks && 8202 "get" in hooks && 8203 ( ret = hooks.get( elem, "value" ) ) !== undefined 8204 ) { 8205 return ret; 8206 } 8207 8208 ret = elem.value; 8209 8210 // Handle most common string cases 8211 if ( typeof ret === "string" ) { 8212 return ret.replace( rreturn, "" ); 8213 } 8214 8215 // Handle cases where value is null/undef or number 8216 return ret == null ? "" : ret; 8217 } 8218 8219 return; 8220 } 8221 8222 valueIsFunction = isFunction( value ); 8223 8224 return this.each( function( i ) { 8225 var val; 8226 8227 if ( this.nodeType !== 1 ) { 8228 return; 8229 } 8230 8231 if ( valueIsFunction ) { 8232 val = value.call( this, i, jQuery( this ).val() ); 8233 } else { 8234 val = value; 8235 } 8236 8237 // Treat null/undefined as ""; convert numbers to string 8238 if ( val == null ) { 8239 val = ""; 8240 8241 } else if ( typeof val === "number" ) { 8242 val += ""; 8243 8244 } else if ( Array.isArray( val ) ) { 8245 val = jQuery.map( val, function( value ) { 8246 return value == null ? "" : value + ""; 8247 } ); 8248 } 8249 8250 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 8251 8252 // If set returns undefined, fall back to normal setting 8253 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { 8254 this.value = val; 8255 } 8256 } ); 8257 } 8258} ); 8259 8260jQuery.extend( { 8261 valHooks: { 8262 option: { 8263 get: function( elem ) { 8264 8265 var val = jQuery.find.attr( elem, "value" ); 8266 return val != null ? 8267 val : 8268 8269 // Support: IE <=10 - 11 only 8270 // option.text throws exceptions (
vendor: 15,164 bytes, lines 8270-8841
8270#14686, #14858) 8271 // Strip and collapse whitespace 8272 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace 8273 stripAndCollapse( jQuery.text( elem ) ); 8274 } 8275 }, 8276 select: { 8277 get: function( elem ) { 8278 var value, option, i, 8279 options = elem.options, 8280 index = elem.selectedIndex, 8281 one = elem.type === "select-one", 8282 values = one ? null : [], 8283 max = one ? index + 1 : options.length; 8284 8285 if ( index < 0 ) { 8286 i = max; 8287 8288 } else { 8289 i = one ? index : 0; 8290 } 8291 8292 // Loop through all the selected options 8293 for ( ; i < max; i++ ) { 8294 option = options[ i ]; 8295 8296 // Support: IE <=9 only 8297 // IE8-9 doesn't update selected after form reset (#2551) 8298 if ( ( option.selected || i === index ) && 8299 8300 // Don't return options that are disabled or in a disabled optgroup 8301 !option.disabled && 8302 ( !option.parentNode.disabled || 8303 !nodeName( option.parentNode, "optgroup" ) ) ) { 8304 8305 // Get the specific value for the option 8306 value = jQuery( option ).val(); 8307 8308 // We don't need an array for one selects 8309 if ( one ) { 8310 return value; 8311 } 8312 8313 // Multi-Selects return an array 8314 values.push( value ); 8315 } 8316 } 8317 8318 return values; 8319 }, 8320 8321 set: function( elem, value ) { 8322 var optionSet, option, 8323 options = elem.options, 8324 values = jQuery.makeArray( value ), 8325 i = options.length; 8326 8327 while ( i-- ) { 8328 option = options[ i ]; 8329 8330 /* eslint-disable no-cond-assign */ 8331 8332 if ( option.selected = 8333 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 8334 ) { 8335 optionSet = true; 8336 } 8337 8338 /* eslint-enable no-cond-assign */ 8339 } 8340 8341 // Force browsers to behave consistently when non-matching value is set 8342 if ( !optionSet ) { 8343 elem.selectedIndex = -1; 8344 } 8345 return values; 8346 } 8347 } 8348 } 8349} ); 8350 8351// Radios and checkboxes getter/setter 8352jQuery.each( [ "radio", "checkbox" ], function() { 8353 jQuery.valHooks[ this ] = { 8354 set: function( elem, value ) { 8355 if ( Array.isArray( value ) ) { 8356 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); 8357 } 8358 } 8359 }; 8360 if ( !support.checkOn ) { 8361 jQuery.valHooks[ this ].get = function( elem ) { 8362 return elem.getAttribute( "value" ) === null ? "on" : elem.value; 8363 }; 8364 } 8365} ); 8366 8367 8368 8369 8370// Return jQuery for attributes-only inclusion 8371 8372 8373support.focusin = "onfocusin" in window; 8374 8375 8376var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 8377 stopPropagationCallback = function( e ) { 8378 e.stopPropagation(); 8379 }; 8380 8381jQuery.extend( jQuery.event, { 8382 8383 trigger: function( event, data, elem, onlyHandlers ) { 8384 8385 var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, 8386 eventPath = [ elem || document ], 8387 type = hasOwn.call( event, "type" ) ? event.type : event, 8388 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; 8389 8390 cur = lastElement = tmp = elem = elem || document; 8391 8392 // Don't do events on text and comment nodes 8393 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 8394 return; 8395 } 8396 8397 // focus/blur morphs to focusin/out; ensure we're not firing them right now 8398 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 8399 return; 8400 } 8401 8402 if ( type.indexOf( "." ) > -1 ) { 8403 8404 // Namespaced trigger; create a regexp to match event type in handle() 8405 namespaces = type.split( "." ); 8406 type = namespaces.shift(); 8407 namespaces.sort(); 8408 } 8409 ontype = type.indexOf( ":" ) < 0 && "on" + type; 8410 8411 // Caller can pass in a jQuery.Event object, Object, or just an event type string 8412 event = event[ jQuery.expando ] ? 8413 event : 8414 new jQuery.Event( type, typeof event === "object" && event ); 8415 8416 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 8417 event.isTrigger = onlyHandlers ? 2 : 3; 8418 event.namespace = namespaces.join( "." ); 8419 event.rnamespace = event.namespace ? 8420 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : 8421 null; 8422 8423 // Clean up the event in case it is being reused 8424 event.result = undefined; 8425 if ( !event.target ) { 8426 event.target = elem; 8427 } 8428 8429 // Clone any incoming data and prepend the event, creating the handler arg list 8430 data = data == null ? 8431 [ event ] : 8432 jQuery.makeArray( data, [ event ] ); 8433 8434 // Allow special events to draw outside the lines 8435 special = jQuery.event.special[ type ] || {}; 8436 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 8437 return; 8438 } 8439 8440 // Determine event propagation path in advance, per W3C events spec (#9951) 8441 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 8442 if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { 8443 8444 bubbleType = special.delegateType || type; 8445 if ( !rfocusMorph.test( bubbleType + type ) ) { 8446 cur = cur.parentNode; 8447 } 8448 for ( ; cur; cur = cur.parentNode ) { 8449 eventPath.push( cur ); 8450 tmp = cur; 8451 } 8452 8453 // Only add window if we got to document (e.g., not plain obj or detached DOM) 8454 if ( tmp === ( elem.ownerDocument || document ) ) { 8455 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 8456 } 8457 } 8458 8459 // Fire handlers on the event path 8460 i = 0; 8461 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { 8462 lastElement = cur; 8463 event.type = i > 1 ? 8464 bubbleType : 8465 special.bindType || type; 8466 8467 // jQuery handler 8468 handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && 8469 dataPriv.get( cur, "handle" ); 8470 if ( handle ) { 8471 handle.apply( cur, data ); 8472 } 8473 8474 // Native handler 8475 handle = ontype && cur[ ontype ]; 8476 if ( handle && handle.apply && acceptData( cur ) ) { 8477 event.result = handle.apply( cur, data ); 8478 if ( event.result === false ) { 8479 event.preventDefault(); 8480 } 8481 } 8482 } 8483 event.type = type; 8484 8485 // If nobody prevented the default action, do it now 8486 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 8487 8488 if ( ( !special._default || 8489 special._default.apply( eventPath.pop(), data ) === false ) && 8490 acceptData( elem ) ) { 8491 8492 // Call a native DOM method on the target with the same name as the event. 8493 // Don't do default actions on window, that's where global variables be (#6170) 8494 if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { 8495 8496 // Don't re-trigger an onFOO event when we call its FOO() method 8497 tmp = elem[ ontype ]; 8498 8499 if ( tmp ) { 8500 elem[ ontype ] = null; 8501 } 8502 8503 // Prevent re-triggering of the same event, since we already bubbled it above 8504 jQuery.event.triggered = type; 8505 8506 if ( event.isPropagationStopped() ) { 8507 lastElement.addEventListener( type, stopPropagationCallback ); 8508 } 8509 8510 elem[ type ](); 8511 8512 if ( event.isPropagationStopped() ) { 8513 lastElement.removeEventListener( type, stopPropagationCallback ); 8514 } 8515 8516 jQuery.event.triggered = undefined; 8517 8518 if ( tmp ) { 8519 elem[ ontype ] = tmp; 8520 } 8521 } 8522 } 8523 } 8524 8525 return event.result; 8526 }, 8527 8528 // Piggyback on a donor event to simulate a different one 8529 // Used only for `focus(in | out)` events 8530 simulate: function( type, elem, event ) { 8531 var e = jQuery.extend( 8532 new jQuery.Event(), 8533 event, 8534 { 8535 type: type, 8536 isSimulated: true 8537 } 8538 ); 8539 8540 jQuery.event.trigger( e, null, elem ); 8541 } 8542 8543} ); 8544 8545jQuery.fn.extend( { 8546 8547 trigger: function( type, data ) { 8548 return this.each( function() { 8549 jQuery.event.trigger( type, data, this ); 8550 } ); 8551 }, 8552 triggerHandler: function( type, data ) { 8553 var elem = this[ 0 ]; 8554 if ( elem ) { 8555 return jQuery.event.trigger( type, data, elem, true ); 8556 } 8557 } 8558} ); 8559 8560 8561// Support: Firefox <=44 8562// Firefox doesn't have focus(in | out) events 8563// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 8564// 8565// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 8566// focus(in | out) events fire after focus & blur events, 8567// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order 8568// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 8569if ( !support.focusin ) { 8570 jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { 8571 8572 // Attach a single capturing handler on the document while someone wants focusin/focusout 8573 var handler = function( event ) { 8574 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); 8575 }; 8576 8577 jQuery.event.special[ fix ] = { 8578 setup: function() { 8579 var doc = this.ownerDocument || this, 8580 attaches = dataPriv.access( doc, fix ); 8581 8582 if ( !attaches ) { 8583 doc.addEventListener( orig, handler, true ); 8584 } 8585 dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); 8586 }, 8587 teardown: function() { 8588 var doc = this.ownerDocument || this, 8589 attaches = dataPriv.access( doc, fix ) - 1; 8590 8591 if ( !attaches ) { 8592 doc.removeEventListener( orig, handler, true ); 8593 dataPriv.remove( doc, fix ); 8594 8595 } else { 8596 dataPriv.access( doc, fix, attaches ); 8597 } 8598 } 8599 }; 8600 } ); 8601} 8602var location = window.location; 8603 8604var nonce = Date.now(); 8605 8606var rquery = ( /\?/ ); 8607 8608 8609 8610// Cross-browser xml parsing 8611jQuery.parseXML = function( data ) { 8612 var xml; 8613 if ( !data || typeof data !== "string" ) { 8614 return null; 8615 } 8616 8617 // Support: IE 9 - 11 only 8618 // IE throws on parseFromString with invalid input. 8619 try { 8620 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); 8621 } catch ( e ) { 8622 xml = undefined; 8623 } 8624 8625 if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 8626 jQuery.error( "Invalid XML: " + data ); 8627 } 8628 return xml; 8629}; 8630 8631 8632var 8633 rbracket = /\[\]$/, 8634 rCRLF = /\r?\n/g, 8635 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 8636 rsubmittable = /^(?:input|select|textarea|keygen)/i; 8637 8638function buildParams( prefix, obj, traditional, add ) { 8639 var name; 8640 8641 if ( Array.isArray( obj ) ) { 8642 8643 // Serialize array item. 8644 jQuery.each( obj, function( i, v ) { 8645 if ( traditional || rbracket.test( prefix ) ) { 8646 8647 // Treat each array item as a scalar. 8648 add( prefix, v ); 8649 8650 } else { 8651 8652 // Item is non-scalar (array or object), encode its numeric index. 8653 buildParams( 8654 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", 8655 v, 8656 traditional, 8657 add 8658 ); 8659 } 8660 } ); 8661 8662 } else if ( !traditional && toType( obj ) === "object" ) { 8663 8664 // Serialize object item. 8665 for ( name in obj ) { 8666 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 8667 } 8668 8669 } else { 8670 8671 // Serialize scalar item. 8672 add( prefix, obj ); 8673 } 8674} 8675 8676// Serialize an array of form elements or a set of 8677// key/values into a query string 8678jQuery.param = function( a, traditional ) { 8679 var prefix, 8680 s = [], 8681 add = function( key, valueOrFunction ) { 8682 8683 // If value is a function, invoke it and use its return value 8684 var value = isFunction( valueOrFunction ) ? 8685 valueOrFunction() : 8686 valueOrFunction; 8687 8688 s[ s.length ] = encodeURIComponent( key ) + "=" + 8689 encodeURIComponent( value == null ? "" : value ); 8690 }; 8691 8692 if ( a == null ) { 8693 return ""; 8694 } 8695 8696 // If an array was passed in, assume that it is an array of form elements. 8697 if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 8698 8699 // Serialize the form elements 8700 jQuery.each( a, function() { 8701 add( this.name, this.value ); 8702 } ); 8703 8704 } else { 8705 8706 // If traditional, encode the "old" way (the way 1.3.2 or older 8707 // did it), otherwise encode params recursively. 8708 for ( prefix in a ) { 8709 buildParams( prefix, a[ prefix ], traditional, add ); 8710 } 8711 } 8712 8713 // Return the resulting serialization 8714 return s.join( "&" ); 8715}; 8716 8717jQuery.fn.extend( { 8718 serialize: function() { 8719 return jQuery.param( this.serializeArray() ); 8720 }, 8721 serializeArray: function() { 8722 return this.map( function() { 8723 8724 // Can add propHook for "elements" to filter or add form elements 8725 var elements = jQuery.prop( this, "elements" ); 8726 return elements ? jQuery.makeArray( elements ) : this; 8727 } ) 8728 .filter( function() { 8729 var type = this.type; 8730 8731 // Use .is( ":disabled" ) so that fieldset[disabled] works 8732 return this.name && !jQuery( this ).is( ":disabled" ) && 8733 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 8734 ( this.checked || !rcheckableType.test( type ) ); 8735 } ) 8736 .map( function( i, elem ) { 8737 var val = jQuery( this ).val(); 8738 8739 if ( val == null ) { 8740 return null; 8741 } 8742 8743 if ( Array.isArray( val ) ) { 8744 return jQuery.map( val, function( val ) { 8745 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8746 } ); 8747 } 8748 8749 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8750 } ).get(); 8751 } 8752} ); 8753 8754 8755var 8756 r20 = /%20/g, 8757 rhash = /#.*$/, 8758 rantiCache = /([?&])_=[^&]*/, 8759 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, 8760 8761 // #7653, #8125, #8152: local protocol detection 8762 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 8763 rnoContent = /^(?:GET|HEAD)$/, 8764 rprotocol = /^\/\//, 8765 8766 /* Prefilters 8767 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 8768 * 2) These are called: 8769 * - BEFORE asking for a transport 8770 * - AFTER param serialization (s.data is a string if s.processData is true) 8771 * 3) key is the dataType 8772 * 4) the catchall symbol "*" can be used 8773 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 8774 */ 8775 prefilters = {}, 8776 8777 /* Transports bindings 8778 * 1) key is the dataType 8779 * 2) the catchall symbol "*" can be used 8780 * 3) selection will start with transport dataType and THEN go to "*" if needed 8781 */ 8782 transports = {}, 8783 8784 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 8785 allTypes = "*/".concat( "*" ), 8786 8787 // Anchor tag for parsing the document origin 8788 originAnchor = document.createElement( "a" ); 8789 originAnchor.href = location.href; 8790 8791// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 8792function addToPrefiltersOrTransports( structure ) { 8793 8794 // dataTypeExpression is optional and defaults to "*" 8795 return function( dataTypeExpression, func ) { 8796 8797 if ( typeof dataTypeExpression !== "string" ) { 8798 func = dataTypeExpression; 8799 dataTypeExpression = "*"; 8800 } 8801 8802 var dataType, 8803 i = 0, 8804 dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; 8805 8806 if ( isFunction( func ) ) { 8807 8808 // For each dataType in the dataTypeExpression 8809 while ( ( dataType = dataTypes[ i++ ] ) ) { 8810 8811 // Prepend if requested 8812 if ( dataType[ 0 ] === "+" ) { 8813 dataType = dataType.slice( 1 ) || "*"; 8814 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); 8815 8816 // Otherwise append 8817 } else { 8818 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); 8819 } 8820 } 8821 } 8822 }; 8823} 8824 8825// Base inspection function for prefilters and transports 8826function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 8827 8828 var inspected = {}, 8829 seekingTransport = ( structure === transports ); 8830 8831 function inspect( dataType ) { 8832 var selected; 8833 inspected[ dataType ] = true; 8834 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 8835 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 8836 if ( typeof dataTypeOrTransport === "string" && 8837 !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 8838 8839 options.dataTypes.unshift( dataTypeOrTransport ); 8840 inspect( dataTypeOrTransport ); 8841 return false;
vendor: 10,690 bytes, lines 8842-9279
8842 } else if ( seekingTransport ) { 8843 return !( selected = dataTypeOrTransport ); 8844 } 8845 } ); 8846 return selected; 8847 } 8848 8849 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 8850} 8851 8852// A special extend for ajax options 8853// that takes "flat" options (not to be deep extended) 8854// Fixes #9887 8855function ajaxExtend( target, src ) { 8856 var key, deep, 8857 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 8858 8859 for ( key in src ) { 8860 if ( src[ key ] !== undefined ) { 8861 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; 8862 } 8863 } 8864 if ( deep ) { 8865 jQuery.extend( true, target, deep ); 8866 } 8867 8868 return target; 8869} 8870 8871/* Handles responses to an ajax request: 8872 * - finds the right dataType (mediates between content-type and expected dataType) 8873 * - returns the corresponding response 8874 */ 8875function ajaxHandleResponses( s, jqXHR, responses ) { 8876 8877 var ct, type, finalDataType, firstDataType, 8878 contents = s.contents, 8879 dataTypes = s.dataTypes; 8880 8881 // Remove auto dataType and get content-type in the process 8882 while ( dataTypes[ 0 ] === "*" ) { 8883 dataTypes.shift(); 8884 if ( ct === undefined ) { 8885 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); 8886 } 8887 } 8888 8889 // Check if we're dealing with a known content-type 8890 if ( ct ) { 8891 for ( type in contents ) { 8892 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8893 dataTypes.unshift( type ); 8894 break; 8895 } 8896 } 8897 } 8898 8899 // Check to see if we have a response for the expected dataType 8900 if ( dataTypes[ 0 ] in responses ) { 8901 finalDataType = dataTypes[ 0 ]; 8902 } else { 8903 8904 // Try convertible dataTypes 8905 for ( type in responses ) { 8906 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { 8907 finalDataType = type; 8908 break; 8909 } 8910 if ( !firstDataType ) { 8911 firstDataType = type; 8912 } 8913 } 8914 8915 // Or just use first one 8916 finalDataType = finalDataType || firstDataType; 8917 } 8918 8919 // If we found a dataType 8920 // We add the dataType to the list if needed 8921 // and return the corresponding response 8922 if ( finalDataType ) { 8923 if ( finalDataType !== dataTypes[ 0 ] ) { 8924 dataTypes.unshift( finalDataType ); 8925 } 8926 return responses[ finalDataType ]; 8927 } 8928} 8929 8930/* Chain conversions given the request and the original response 8931 * Also sets the responseXXX fields on the jqXHR instance 8932 */ 8933function ajaxConvert( s, response, jqXHR, isSuccess ) { 8934 var conv2, current, conv, tmp, prev, 8935 converters = {}, 8936 8937 // Work with a copy of dataTypes in case we need to modify it for conversion 8938 dataTypes = s.dataTypes.slice(); 8939 8940 // Create converters map with lowercased keys 8941 if ( dataTypes[ 1 ] ) { 8942 for ( conv in s.converters ) { 8943 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 8944 } 8945 } 8946 8947 current = dataTypes.shift(); 8948 8949 // Convert to each sequential dataType 8950 while ( current ) { 8951 8952 if ( s.responseFields[ current ] ) { 8953 jqXHR[ s.responseFields[ current ] ] = response; 8954 } 8955 8956 // Apply the dataFilter if provided 8957 if ( !prev && isSuccess && s.dataFilter ) { 8958 response = s.dataFilter( response, s.dataType ); 8959 } 8960 8961 prev = current; 8962 current = dataTypes.shift(); 8963 8964 if ( current ) { 8965 8966 // There's only work to do if current dataType is non-auto 8967 if ( current === "*" ) { 8968 8969 current = prev; 8970 8971 // Convert response if prev dataType is non-auto and differs from current 8972 } else if ( prev !== "*" && prev !== current ) { 8973 8974 // Seek a direct converter 8975 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 8976 8977 // If none found, seek a pair 8978 if ( !conv ) { 8979 for ( conv2 in converters ) { 8980 8981 // If conv2 outputs current 8982 tmp = conv2.split( " " ); 8983 if ( tmp[ 1 ] === current ) { 8984 8985 // If prev can be converted to accepted input 8986 conv = converters[ prev + " " + tmp[ 0 ] ] || 8987 converters[ "* " + tmp[ 0 ] ]; 8988 if ( conv ) { 8989 8990 // Condense equivalence converters 8991 if ( conv === true ) { 8992 conv = converters[ conv2 ]; 8993 8994 // Otherwise, insert the intermediate dataType 8995 } else if ( converters[ conv2 ] !== true ) { 8996 current = tmp[ 0 ]; 8997 dataTypes.unshift( tmp[ 1 ] ); 8998 } 8999 break; 9000 } 9001 } 9002 } 9003 } 9004 9005 // Apply converter (if not an equivalence) 9006 if ( conv !== true ) { 9007 9008 // Unless errors are allowed to bubble, catch and return them 9009 if ( conv && s.throws ) { 9010 response = conv( response ); 9011 } else { 9012 try { 9013 response = conv( response ); 9014 } catch ( e ) { 9015 return { 9016 state: "parsererror", 9017 error: conv ? e : "No conversion from " + prev + " to " + current 9018 }; 9019 } 9020 } 9021 } 9022 } 9023 } 9024 } 9025 9026 return { state: "success", data: response }; 9027} 9028 9029jQuery.extend( { 9030 9031 // Counter for holding the number of active queries 9032 active: 0, 9033 9034 // Last-Modified header cache for next request 9035 lastModified: {}, 9036 etag: {}, 9037 9038 ajaxSettings: { 9039 url: location.href, 9040 type: "GET", 9041 isLocal: rlocalProtocol.test( location.protocol ), 9042 global: true, 9043 processData: true, 9044 async: true, 9045 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 9046 9047 /* 9048 timeout: 0, 9049 data: null, 9050 dataType: null, 9051 username: null, 9052 password: null, 9053 cache: null, 9054 throws: false, 9055 traditional: false, 9056 headers: {}, 9057 */ 9058 9059 accepts: { 9060 "*": allTypes, 9061 text: "text/plain", 9062 html: "text/html", 9063 xml: "application/xml, text/xml", 9064 json: "application/json, text/javascript" 9065 }, 9066 9067 contents: { 9068 xml: /\bxml\b/, 9069 html: /\bhtml/, 9070 json: /\bjson\b/ 9071 }, 9072 9073 responseFields: { 9074 xml: "responseXML", 9075 text: "responseText", 9076 json: "responseJSON" 9077 }, 9078 9079 // Data converters 9080 // Keys separate source (or catchall "*") and destination types with a single space 9081 converters: { 9082 9083 // Convert anything to text 9084 "* text": String, 9085 9086 // Text to html (true = no transformation) 9087 "text html": true, 9088 9089 // Evaluate text as a json expression 9090 "text json": JSON.parse, 9091 9092 // Parse text as xml 9093 "text xml": jQuery.parseXML 9094 }, 9095 9096 // For options that shouldn't be deep extended: 9097 // you can add your own custom options here if 9098 // and when you create one that shouldn't be 9099 // deep extended (see ajaxExtend) 9100 flatOptions: { 9101 url: true, 9102 context: true 9103 } 9104 }, 9105 9106 // Creates a full fledged settings object into target 9107 // with both ajaxSettings and settings fields. 9108 // If target is omitted, writes into ajaxSettings. 9109 ajaxSetup: function( target, settings ) { 9110 return settings ? 9111 9112 // Building a settings object 9113 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 9114 9115 // Extending ajaxSettings 9116 ajaxExtend( jQuery.ajaxSettings, target ); 9117 }, 9118 9119 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 9120 ajaxTransport: addToPrefiltersOrTransports( transports ), 9121 9122 // Main method 9123 ajax: function( url, options ) { 9124 9125 // If url is an object, simulate pre-1.5 signature 9126 if ( typeof url === "object" ) { 9127 options = url; 9128 url = undefined; 9129 } 9130 9131 // Force options to be an object 9132 options = options || {}; 9133 9134 var transport, 9135 9136 // URL without anti-cache param 9137 cacheURL, 9138 9139 // Response headers 9140 responseHeadersString, 9141 responseHeaders, 9142 9143 // timeout handle 9144 timeoutTimer, 9145 9146 // Url cleanup var 9147 urlAnchor, 9148 9149 // Request state (becomes false upon send and true upon completion) 9150 completed, 9151 9152 // To know if global events are to be dispatched 9153 fireGlobals, 9154 9155 // Loop variable 9156 i, 9157 9158 // uncached part of the url 9159 uncached, 9160 9161 // Create the final options object 9162 s = jQuery.ajaxSetup( {}, options ), 9163 9164 // Callbacks context 9165 callbackContext = s.context || s, 9166 9167 // Context for global events is callbackContext if it is a DOM node or jQuery collection 9168 globalEventContext = s.context && 9169 ( callbackContext.nodeType || callbackContext.jquery ) ? 9170 jQuery( callbackContext ) : 9171 jQuery.event, 9172 9173 // Deferreds 9174 deferred = jQuery.Deferred(), 9175 completeDeferred = jQuery.Callbacks( "once memory" ), 9176 9177 // Status-dependent callbacks 9178 statusCode = s.statusCode || {}, 9179 9180 // Headers (they are sent all at once) 9181 requestHeaders = {}, 9182 requestHeadersNames = {}, 9183 9184 // Default abort message 9185 strAbort = "canceled", 9186 9187 // Fake xhr 9188 jqXHR = { 9189 readyState: 0, 9190 9191 // Builds headers hashtable if needed 9192 getResponseHeader: function( key ) { 9193 var match; 9194 if ( completed ) { 9195 if ( !responseHeaders ) { 9196 responseHeaders = {}; 9197 while ( ( match = rheaders.exec( responseHeadersString ) ) ) { 9198 responseHeaders[ match[ 1 ].toLowerCase() + " " ] = 9199 ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) 9200 .concat( match[ 2 ] ); 9201 } 9202 } 9203 match = responseHeaders[ key.toLowerCase() + " " ]; 9204 } 9205 return match == null ? null : match.join( ", " ); 9206 }, 9207 9208 // Raw string 9209 getAllResponseHeaders: function() { 9210 return completed ? responseHeadersString : null; 9211 }, 9212 9213 // Caches the header 9214 setRequestHeader: function( name, value ) { 9215 if ( completed == null ) { 9216 name = requestHeadersNames[ name.toLowerCase() ] = 9217 requestHeadersNames[ name.toLowerCase() ] || name; 9218 requestHeaders[ name ] = value; 9219 } 9220 return this; 9221 }, 9222 9223 // Overrides response content-type header 9224 overrideMimeType: function( type ) { 9225 if ( completed == null ) { 9226 s.mimeType = type; 9227 } 9228 return this; 9229 }, 9230 9231 // Status-dependent callbacks 9232 statusCode: function( map ) { 9233 var code; 9234 if ( map ) { 9235 if ( completed ) { 9236 9237 // Execute the appropriate callbacks 9238 jqXHR.always( map[ jqXHR.status ] ); 9239 } else { 9240 9241 // Lazy-add the new callbacks in a way that preserves old ones 9242 for ( code in map ) { 9243 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 9244 } 9245 } 9246 } 9247 return this; 9248 }, 9249 9250 // Cancel the request 9251 abort: function( statusText ) { 9252 var finalText = statusText || strAbort; 9253 if ( transport ) { 9254 transport.abort( finalText ); 9255 } 9256 done( 0, finalText ); 9257 return this; 9258 } 9259 }; 9260 9261 // Attach deferreds 9262 deferred.promise( jqXHR ); 9263 9264 // Add protocol if not provided (prefilters might expect it) 9265 // Handle falsy url in the settings object (#10093: consistency with old signature) 9266 // We also use the url parameter if available 9267 s.url = ( ( url || s.url || location.href ) + "" ) 9268 .replace( rprotocol, location.protocol + "//" ); 9269 9270 // Alias method option to type as per ticket #12004 9271 s.type = options.method || options.type || s.method || s.type; 9272 9273 // Extract dataTypes list 9274 s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; 9275 9276 // A cross-domain request is in order when the origin doesn't match the current origin. 9277 if ( s.crossDomain == null ) { 9278 urlAnchor = document.createElement( "a" ); 9279
vendor: 16,732 bytes, lines 9280-9934
9280 // Support: IE <=8 - 11, Edge 12 - 15 9281 // IE throws exception on accessing the href property if url is malformed, 9282 // e.g. http://example.com:80x/ 9283 try { 9284 urlAnchor.href = s.url; 9285 9286 // Support: IE <=8 - 11 only 9287 // Anchor's host property isn't correctly set when s.url is relative 9288 urlAnchor.href = urlAnchor.href; 9289 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== 9290 urlAnchor.protocol + "//" + urlAnchor.host; 9291 } catch ( e ) { 9292 9293 // If there is an error parsing the URL, assume it is crossDomain, 9294 // it can be rejected by the transport if it is invalid 9295 s.crossDomain = true; 9296 } 9297 } 9298 9299 // Convert data if not already a string 9300 if ( s.data && s.processData && typeof s.data !== "string" ) { 9301 s.data = jQuery.param( s.data, s.traditional ); 9302 } 9303 9304 // Apply prefilters 9305 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 9306 9307 // If request was aborted inside a prefilter, stop there 9308 if ( completed ) { 9309 return jqXHR; 9310 } 9311 9312 // We can fire global events as of now if asked to 9313 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) 9314 fireGlobals = jQuery.event && s.global; 9315 9316 // Watch for a new set of requests 9317 if ( fireGlobals && jQuery.active++ === 0 ) { 9318 jQuery.event.trigger( "ajaxStart" ); 9319 } 9320 9321 // Uppercase the type 9322 s.type = s.type.toUpperCase(); 9323 9324 // Determine if request has content 9325 s.hasContent = !rnoContent.test( s.type ); 9326 9327 // Save the URL in case we're toying with the If-Modified-Since 9328 // and/or If-None-Match header later on 9329 // Remove hash to simplify url manipulation 9330 cacheURL = s.url.replace( rhash, "" ); 9331 9332 // More options handling for requests with no content 9333 if ( !s.hasContent ) { 9334 9335 // Remember the hash so we can put it back 9336 uncached = s.url.slice( cacheURL.length ); 9337 9338 // If data is available and should be processed, append data to url 9339 if ( s.data && ( s.processData || typeof s.data === "string" ) ) { 9340 cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; 9341 9342 // #9682: remove data so that it's not used in an eventual retry 9343 delete s.data; 9344 } 9345 9346 // Add or update anti-cache param if needed 9347 if ( s.cache === false ) { 9348 cacheURL = cacheURL.replace( rantiCache, "$1" ); 9349 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; 9350 } 9351 9352 // Put hash and anti-cache on the URL that will be requested (gh-1732) 9353 s.url = cacheURL + uncached; 9354 9355 // Change '%20' to '+' if this is encoded form body content (gh-2658) 9356 } else if ( s.data && s.processData && 9357 ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { 9358 s.data = s.data.replace( r20, "+" ); 9359 } 9360 9361 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9362 if ( s.ifModified ) { 9363 if ( jQuery.lastModified[ cacheURL ] ) { 9364 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 9365 } 9366 if ( jQuery.etag[ cacheURL ] ) { 9367 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 9368 } 9369 } 9370 9371 // Set the correct header, if data is being sent 9372 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 9373 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 9374 } 9375 9376 // Set the Accepts header for the server, depending on the dataType 9377 jqXHR.setRequestHeader( 9378 "Accept", 9379 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? 9380 s.accepts[ s.dataTypes[ 0 ] ] + 9381 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 9382 s.accepts[ "*" ] 9383 ); 9384 9385 // Check for headers option 9386 for ( i in s.headers ) { 9387 jqXHR.setRequestHeader( i, s.headers[ i ] ); 9388 } 9389 9390 // Allow custom headers/mimetypes and early abort 9391 if ( s.beforeSend && 9392 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { 9393 9394 // Abort if not done already and return 9395 return jqXHR.abort(); 9396 } 9397 9398 // Aborting is no longer a cancellation 9399 strAbort = "abort"; 9400 9401 // Install callbacks on deferreds 9402 completeDeferred.add( s.complete ); 9403 jqXHR.done( s.success ); 9404 jqXHR.fail( s.error ); 9405 9406 // Get transport 9407 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 9408 9409 // If no transport, we auto-abort 9410 if ( !transport ) { 9411 done( -1, "No Transport" ); 9412 } else { 9413 jqXHR.readyState = 1; 9414 9415 // Send global event 9416 if ( fireGlobals ) { 9417 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 9418 } 9419 9420 // If request was aborted inside ajaxSend, stop there 9421 if ( completed ) { 9422 return jqXHR; 9423 } 9424 9425 // Timeout 9426 if ( s.async && s.timeout > 0 ) { 9427 timeoutTimer = window.setTimeout( function() { 9428 jqXHR.abort( "timeout" ); 9429 }, s.timeout ); 9430 } 9431 9432 try { 9433 completed = false; 9434 transport.send( requestHeaders, done ); 9435 } catch ( e ) { 9436 9437 // Rethrow post-completion exceptions 9438 if ( completed ) { 9439 throw e; 9440 } 9441 9442 // Propagate others as results 9443 done( -1, e ); 9444 } 9445 } 9446 9447 // Callback for when everything is done 9448 function done( status, nativeStatusText, responses, headers ) { 9449 var isSuccess, success, error, response, modified, 9450 statusText = nativeStatusText; 9451 9452 // Ignore repeat invocations 9453 if ( completed ) { 9454 return; 9455 } 9456 9457 completed = true; 9458 9459 // Clear timeout if it exists 9460 if ( timeoutTimer ) { 9461 window.clearTimeout( timeoutTimer ); 9462 } 9463 9464 // Dereference transport for early garbage collection 9465 // (no matter how long the jqXHR object will be used) 9466 transport = undefined; 9467 9468 // Cache response headers 9469 responseHeadersString = headers || ""; 9470 9471 // Set readyState 9472 jqXHR.readyState = status > 0 ? 4 : 0; 9473 9474 // Determine if successful 9475 isSuccess = status >= 200 && status < 300 || status === 304; 9476 9477 // Get response data 9478 if ( responses ) { 9479 response = ajaxHandleResponses( s, jqXHR, responses ); 9480 } 9481 9482 // Convert no matter what (that way responseXXX fields are always set) 9483 response = ajaxConvert( s, response, jqXHR, isSuccess ); 9484 9485 // If successful, handle type chaining 9486 if ( isSuccess ) { 9487 9488 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9489 if ( s.ifModified ) { 9490 modified = jqXHR.getResponseHeader( "Last-Modified" ); 9491 if ( modified ) { 9492 jQuery.lastModified[ cacheURL ] = modified; 9493 } 9494 modified = jqXHR.getResponseHeader( "etag" ); 9495 if ( modified ) { 9496 jQuery.etag[ cacheURL ] = modified; 9497 } 9498 } 9499 9500 // if no content 9501 if ( status === 204 || s.type === "HEAD" ) { 9502 statusText = "nocontent"; 9503 9504 // if not modified 9505 } else if ( status === 304 ) { 9506 statusText = "notmodified"; 9507 9508 // If we have data, let's convert it 9509 } else { 9510 statusText = response.state; 9511 success = response.data; 9512 error = response.error; 9513 isSuccess = !error; 9514 } 9515 } else { 9516 9517 // Extract error from statusText and normalize for non-aborts 9518 error = statusText; 9519 if ( status || !statusText ) { 9520 statusText = "error"; 9521 if ( status < 0 ) { 9522 status = 0; 9523 } 9524 } 9525 } 9526 9527 // Set data for the fake xhr object 9528 jqXHR.status = status; 9529 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 9530 9531 // Success/Error 9532 if ( isSuccess ) { 9533 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 9534 } else { 9535 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 9536 } 9537 9538 // Status-dependent callbacks 9539 jqXHR.statusCode( statusCode ); 9540 statusCode = undefined; 9541 9542 if ( fireGlobals ) { 9543 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 9544 [ jqXHR, s, isSuccess ? success : error ] ); 9545 } 9546 9547 // Complete 9548 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 9549 9550 if ( fireGlobals ) { 9551 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 9552 9553 // Handle the global AJAX counter 9554 if ( !( --jQuery.active ) ) { 9555 jQuery.event.trigger( "ajaxStop" ); 9556 } 9557 } 9558 } 9559 9560 return jqXHR; 9561 }, 9562 9563 getJSON: function( url, data, callback ) { 9564 return jQuery.get( url, data, callback, "json" ); 9565 }, 9566 9567 getScript: function( url, callback ) { 9568 return jQuery.get( url, undefined, callback, "script" ); 9569 } 9570} ); 9571 9572jQuery.each( [ "get", "post" ], function( i, method ) { 9573 jQuery[ method ] = function( url, data, callback, type ) { 9574 9575 // Shift arguments if data argument was omitted 9576 if ( isFunction( data ) ) { 9577 type = type || callback; 9578 callback = data; 9579 data = undefined; 9580 } 9581 9582 // The url can be an options object (which then must have .url) 9583 return jQuery.ajax( jQuery.extend( { 9584 url: url, 9585 type: method, 9586 dataType: type, 9587 data: data, 9588 success: callback 9589 }, jQuery.isPlainObject( url ) && url ) ); 9590 }; 9591} ); 9592 9593 9594jQuery._evalUrl = function( url, options ) { 9595 return jQuery.ajax( { 9596 url: url, 9597 9598 // Make this explicit, since user can override this through ajaxSetup (#11264) 9599 type: "GET", 9600 dataType: "script", 9601 cache: true, 9602 async: false, 9603 global: false, 9604 9605 // Only evaluate the response if it is successful (gh-4126) 9606 // dataFilter is not invoked for failure responses, so using it instead 9607 // of the default converter is kludgy but it works. 9608 converters: { 9609 "text script": function() {} 9610 }, 9611 dataFilter: function( response ) { 9612 jQuery.globalEval( response, options ); 9613 } 9614 } ); 9615}; 9616 9617 9618jQuery.fn.extend( { 9619 wrapAll: function( html ) { 9620 var wrap; 9621 9622 if ( this[ 0 ] ) { 9623 if ( isFunction( html ) ) { 9624 html = html.call( this[ 0 ] ); 9625 } 9626 9627 // The elements to wrap the target around 9628 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); 9629 9630 if ( this[ 0 ].parentNode ) { 9631 wrap.insertBefore( this[ 0 ] ); 9632 } 9633 9634 wrap.map( function() { 9635 var elem = this; 9636 9637 while ( elem.firstElementChild ) { 9638 elem = elem.firstElementChild; 9639 } 9640 9641 return elem; 9642 } ).append( this ); 9643 } 9644 9645 return this; 9646 }, 9647 9648 wrapInner: function( html ) { 9649 if ( isFunction( html ) ) { 9650 return this.each( function( i ) { 9651 jQuery( this ).wrapInner( html.call( this, i ) ); 9652 } ); 9653 } 9654 9655 return this.each( function() { 9656 var self = jQuery( this ), 9657 contents = self.contents(); 9658 9659 if ( contents.length ) { 9660 contents.wrapAll( html ); 9661 9662 } else { 9663 self.append( html ); 9664 } 9665 } ); 9666 }, 9667 9668 wrap: function( html ) { 9669 var htmlIsFunction = isFunction( html ); 9670 9671 return this.each( function( i ) { 9672 jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); 9673 } ); 9674 }, 9675 9676 unwrap: function( selector ) { 9677 this.parent( selector ).not( "body" ).each( function() { 9678 jQuery( this ).replaceWith( this.childNodes ); 9679 } ); 9680 return this; 9681 } 9682} ); 9683 9684 9685jQuery.expr.pseudos.hidden = function( elem ) { 9686 return !jQuery.expr.pseudos.visible( elem ); 9687}; 9688jQuery.expr.pseudos.visible = function( elem ) { 9689 return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); 9690}; 9691 9692 9693 9694 9695jQuery.ajaxSettings.xhr = function() { 9696 try { 9697 return new window.XMLHttpRequest(); 9698 } catch ( e ) {} 9699}; 9700 9701var xhrSuccessStatus = { 9702 9703 // File protocol always yields status code 0, assume 200 9704 0: 200, 9705 9706 // Support: IE <=9 only 9707 // #1450: sometimes IE returns 1223 when it should be 204 9708 1223: 204 9709 }, 9710 xhrSupported = jQuery.ajaxSettings.xhr(); 9711 9712support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 9713support.ajax = xhrSupported = !!xhrSupported; 9714 9715jQuery.ajaxTransport( function( options ) { 9716 var callback, errorCallback; 9717 9718 // Cross domain only allowed if supported through XMLHttpRequest 9719 if ( support.cors || xhrSupported && !options.crossDomain ) { 9720 return { 9721 send: function( headers, complete ) { 9722 var i, 9723 xhr = options.xhr(); 9724 9725 xhr.open( 9726 options.type, 9727 options.url, 9728 options.async, 9729 options.username, 9730 options.password 9731 ); 9732 9733 // Apply custom fields if provided 9734 if ( options.xhrFields ) { 9735 for ( i in options.xhrFields ) { 9736 xhr[ i ] = options.xhrFields[ i ]; 9737 } 9738 } 9739 9740 // Override mime type if needed 9741 if ( options.mimeType && xhr.overrideMimeType ) { 9742 xhr.overrideMimeType( options.mimeType ); 9743 } 9744 9745 // X-Requested-With header 9746 // For cross-domain requests, seeing as conditions for a preflight are 9747 // akin to a jigsaw puzzle, we simply never set it to be sure. 9748 // (it can always be set on a per-request basis or even using ajaxSetup) 9749 // For same-domain requests, won't change header if already provided. 9750 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { 9751 headers[ "X-Requested-With" ] = "XMLHttpRequest"; 9752 } 9753 9754 // Set headers 9755 for ( i in headers ) { 9756 xhr.setRequestHeader( i, headers[ i ] ); 9757 } 9758 9759 // Callback 9760 callback = function( type ) { 9761 return function() { 9762 if ( callback ) { 9763 callback = errorCallback = xhr.onload = 9764 xhr.onerror = xhr.onabort = xhr.ontimeout = 9765 xhr.onreadystatechange = null; 9766 9767 if ( type === "abort" ) { 9768 xhr.abort(); 9769 } else if ( type === "error" ) { 9770 9771 // Support: IE <=9 only 9772 // On a manual native abort, IE9 throws 9773 // errors on any property access that is not readyState 9774 if ( typeof xhr.status !== "number" ) { 9775 complete( 0, "error" ); 9776 } else { 9777 complete( 9778 9779 // File: protocol always yields status 0; see #8605, #14207 9780 xhr.status, 9781 xhr.statusText 9782 ); 9783 } 9784 } else { 9785 complete( 9786 xhrSuccessStatus[ xhr.status ] || xhr.status, 9787 xhr.statusText, 9788 9789 // Support: IE <=9 only 9790 // IE9 has no XHR2 but throws on binary (trac-11426) 9791 // For XHR2 non-text, let the caller handle it (gh-2498) 9792 ( xhr.responseType || "text" ) !== "text" || 9793 typeof xhr.responseText !== "string" ? 9794 { binary: xhr.response } : 9795 { text: xhr.responseText }, 9796 xhr.getAllResponseHeaders() 9797 ); 9798 } 9799 } 9800 }; 9801 }; 9802 9803 // Listen to events 9804 xhr.onload = callback(); 9805 errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); 9806 9807 // Support: IE 9 only 9808 // Use onreadystatechange to replace onabort 9809 // to handle uncaught aborts 9810 if ( xhr.onabort !== undefined ) { 9811 xhr.onabort = errorCallback; 9812 } else { 9813 xhr.onreadystatechange = function() { 9814 9815 // Check readyState before timeout as it changes 9816 if ( xhr.readyState === 4 ) { 9817 9818 // Allow onerror to be called first, 9819 // but that will not handle a native abort 9820 // Also, save errorCallback to a variable 9821 // as xhr.onerror cannot be accessed 9822 window.setTimeout( function() { 9823 if ( callback ) { 9824 errorCallback(); 9825 } 9826 } ); 9827 } 9828 }; 9829 } 9830 9831 // Create the abort callback 9832 callback = callback( "abort" ); 9833 9834 try { 9835 9836 // Do send the request (this may raise an exception) 9837 xhr.send( options.hasContent && options.data || null ); 9838 } catch ( e ) { 9839 9840 // #14683: Only rethrow if this hasn't been notified as an error yet 9841 if ( callback ) { 9842 throw e; 9843 } 9844 } 9845 }, 9846 9847 abort: function() { 9848 if ( callback ) { 9849 callback(); 9850 } 9851 } 9852 }; 9853 } 9854} ); 9855 9856 9857 9858 9859// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) 9860jQuery.ajaxPrefilter( function( s ) { 9861 if ( s.crossDomain ) { 9862 s.contents.script = false; 9863 } 9864} ); 9865 9866// Install script dataType 9867jQuery.ajaxSetup( { 9868 accepts: { 9869 script: "text/javascript, application/javascript, " + 9870 "application/ecmascript, application/x-ecmascript" 9871 }, 9872 contents: { 9873 script: /\b(?:java|ecma)script\b/ 9874 }, 9875 converters: { 9876 "text script": function( text ) { 9877 jQuery.globalEval( text ); 9878 return text; 9879 } 9880 } 9881} ); 9882 9883// Handle cache's special case and crossDomain 9884jQuery.ajaxPrefilter( "script", function( s ) { 9885 if ( s.cache === undefined ) { 9886 s.cache = false; 9887 } 9888 if ( s.crossDomain ) { 9889 s.type = "GET"; 9890 } 9891} ); 9892 9893// Bind script tag hack transport 9894jQuery.ajaxTransport( "script", function( s ) { 9895 9896 // This transport only deals with cross domain or forced-by-attrs requests 9897 if ( s.crossDomain || s.scriptAttrs ) { 9898 var script, callback; 9899 return { 9900 send: function( _, complete ) { 9901 script = jQuery( "<script>" ) 9902 .attr( s.scriptAttrs || {} ) 9903 .prop( { charset: s.scriptCharset, src: s.url } ) 9904 .on( "load error", callback = function( evt ) { 9905 script.remove(); 9906 callback = null; 9907 if ( evt ) { 9908 complete( evt.type === "error" ? 404 : 200, evt.type ); 9909 } 9910 } ); 9911 9912 // Use native DOM manipulation to avoid our domManip AJAX trickery 9913 document.head.appendChild( script[ 0 ] ); 9914 }, 9915 abort: function() { 9916 if ( callback ) { 9917 callback(); 9918 } 9919 } 9920 }; 9921 } 9922} ); 9923 9924 9925 9926 9927var oldCallbacks = [], 9928 rjsonp = /(=)\?(?=&|$)|\?\?/; 9929 9930// Default jsonp settings 9931jQuery.ajaxSetup( { 9932 jsonp: "callback", 9933 jsonpCallback: function() { 9934 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce
vendor: 5,879 bytes, lines 9934-10150
9934++ ) ); 9935 this[ callback ] = true; 9936 return callback; 9937 } 9938} ); 9939 9940// Detect, normalize options and install callbacks for jsonp requests 9941jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 9942 9943 var callbackName, overwritten, responseContainer, 9944 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 9945 "url" : 9946 typeof s.data === "string" && 9947 ( s.contentType || "" ) 9948 .indexOf( "application/x-www-form-urlencoded" ) === 0 && 9949 rjsonp.test( s.data ) && "data" 9950 ); 9951 9952 // Handle iff the expected data type is "jsonp" or we have a parameter to set 9953 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 9954 9955 // Get callback name, remembering preexisting value associated with it 9956 callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ? 9957 s.jsonpCallback() : 9958 s.jsonpCallback; 9959 9960 // Insert callback into url or form data 9961 if ( jsonProp ) { 9962 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 9963 } else if ( s.jsonp !== false ) { 9964 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 9965 } 9966 9967 // Use data converter to retrieve json after script execution 9968 s.converters[ "script json" ] = function() { 9969 if ( !responseContainer ) { 9970 jQuery.error( callbackName + " was not called" ); 9971 } 9972 return responseContainer[ 0 ]; 9973 }; 9974 9975 // Force json dataType 9976 s.dataTypes[ 0 ] = "json"; 9977 9978 // Install callback 9979 overwritten = window[ callbackName ]; 9980 window[ callbackName ] = function() { 9981 responseContainer = arguments; 9982 }; 9983 9984 // Clean-up function (fires after converters) 9985 jqXHR.always( function() { 9986 9987 // If previous value didn't exist - remove it 9988 if ( overwritten === undefined ) { 9989 jQuery( window ).removeProp( callbackName ); 9990 9991 // Otherwise restore preexisting value 9992 } else { 9993 window[ callbackName ] = overwritten; 9994 } 9995 9996 // Save back as free 9997 if ( s[ callbackName ] ) { 9998 9999 // Make sure that re-using the options doesn't screw things around 10000 s.jsonpCallback = originalSettings.jsonpCallback; 10001 10002 // Save the callback name for future use 10003 oldCallbacks.push( callbackName ); 10004 } 10005 10006 // Call if it was a function and we have a response 10007 if ( responseContainer && isFunction( overwritten ) ) { 10008 overwritten( responseContainer[ 0 ] ); 10009 } 10010 10011 responseContainer = overwritten = undefined; 10012 } ); 10013 10014 // Delegate to script 10015 return "script"; 10016 } 10017} ); 10018 10019 10020 10021 10022// Support: Safari 8 only 10023// In Safari 8 documents created via document.implementation.createHTMLDocument 10024// collapse sibling forms: the second one becomes a child of the first one. 10025// Because of that, this security measure has to be disabled in Safari 8. 10026// https://bugs.webkit.org/show_bug.cgi?id=137337 10027support.createHTMLDocument = ( function() { 10028 var body = document.implementation.createHTMLDocument( "" ).body; 10029 body.innerHTML = "<form></form><form></form>"; 10030 return body.childNodes.length === 2; 10031} )(); 10032 10033 10034// Argument "data" should be string of html 10035// context (optional): If specified, the fragment will be created in this context, 10036// defaults to document 10037// keepScripts (optional): If true, will include scripts passed in the html string 10038jQuery.parseHTML = function( data, context, keepScripts ) { 10039 if ( typeof data !== "string" ) { 10040 return []; 10041 } 10042 if ( typeof context === "boolean" ) { 10043 keepScripts = context; 10044 context = false; 10045 } 10046 10047 var base, parsed, scripts; 10048 10049 if ( !context ) { 10050 10051 // Stop scripts or inline event handlers from being executed immediately 10052 // by using document.implementation 10053 if ( support.createHTMLDocument ) { 10054 context = document.implementation.createHTMLDocument( "" ); 10055 10056 // Set the base href for the created document 10057 // so any parsed elements with URLs 10058 // are based on the document's URL (gh-2965) 10059 base = context.createElement( "base" ); 10060 base.href = document.location.href; 10061 context.head.appendChild( base ); 10062 } else { 10063 context = document; 10064 } 10065 } 10066 10067 parsed = rsingleTag.exec( data ); 10068 scripts = !keepScripts && []; 10069 10070 // Single tag 10071 if ( parsed ) { 10072 return [ context.createElement( parsed[ 1 ] ) ]; 10073 } 10074 10075 parsed = buildFragment( [ data ], context, scripts ); 10076 10077 if ( scripts && scripts.length ) { 10078 jQuery( scripts ).remove(); 10079 } 10080 10081 return jQuery.merge( [], parsed.childNodes ); 10082}; 10083 10084 10085/** 10086 * Load a url into a page 10087 */ 10088jQuery.fn.load = function( url, params, callback ) { 10089 var selector, type, response, 10090 self = this, 10091 off = url.indexOf( " " ); 10092 10093 if ( off > -1 ) { 10094 selector = stripAndCollapse( url.slice( off ) ); 10095 url = url.slice( 0, off ); 10096 } 10097 10098 // If it's a function 10099 if ( isFunction( params ) ) { 10100 10101 // We assume that it's the callback 10102 callback = params; 10103 params = undefined; 10104 10105 // Otherwise, build a param string 10106 } else if ( params && typeof params === "object" ) { 10107 type = "POST"; 10108 } 10109 10110 // If we have elements to modify, make the request 10111 if ( self.length > 0 ) { 10112 jQuery.ajax( { 10113 url: url, 10114 10115 // If "type" variable is undefined, then "GET" method will be used. 10116 // Make value of this field explicit since 10117 // user can override it through ajaxSetup method 10118 type: type || "GET", 10119 dataType: "html", 10120 data: params 10121 } ).done( function( responseText ) { 10122 10123 // Save response for use in complete callback 10124 response = arguments; 10125 10126 self.html( selector ? 10127 10128 // If a selector was specified, locate the right elements in a dummy div 10129 // Exclude scripts to avoid IE 'Permission Denied' errors 10130 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : 10131 10132 // Otherwise use the full result 10133 responseText ); 10134 10135 // If the request succeeds, this function gets "data", "status", "jqXHR" 10136 // but they are ignored because response was set above. 10137 // If it fails, this function gets "jqXHR", "status", "error" 10138 } ).always( callback && function( jqXHR, status ) { 10139 self.each( function() { 10140 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); 10141 } ); 10142 } ); 10143 } 10144 10145 return this; 10146}; 10147 10148 10149 10150
vendor: 11,997 bytes, lines 10151-10555
10151// Attach a bunch of functions for handling common AJAX events 10152jQuery.each( [ 10153 "ajaxStart", 10154 "ajaxStop", 10155 "ajaxComplete", 10156 "ajaxError", 10157 "ajaxSuccess", 10158 "ajaxSend" 10159], function( i, type ) { 10160 jQuery.fn[ type ] = function( fn ) { 10161 return this.on( type, fn ); 10162 }; 10163} ); 10164 10165 10166 10167 10168jQuery.expr.pseudos.animated = function( elem ) { 10169 return jQuery.grep( jQuery.timers, function( fn ) { 10170 return elem === fn.elem; 10171 } ).length; 10172}; 10173 10174 10175 10176 10177jQuery.offset = { 10178 setOffset: function( elem, options, i ) { 10179 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 10180 position = jQuery.css( elem, "position" ), 10181 curElem = jQuery( elem ), 10182 props = {}; 10183 10184 // Set position first, in-case top/left are set even on static elem 10185 if ( position === "static" ) { 10186 elem.style.position = "relative"; 10187 } 10188 10189 curOffset = curElem.offset(); 10190 curCSSTop = jQuery.css( elem, "top" ); 10191 curCSSLeft = jQuery.css( elem, "left" ); 10192 calculatePosition = ( position === "absolute" || position === "fixed" ) && 10193 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; 10194 10195 // Need to be able to calculate position if either 10196 // top or left is auto and position is either absolute or fixed 10197 if ( calculatePosition ) { 10198 curPosition = curElem.position(); 10199 curTop = curPosition.top; 10200 curLeft = curPosition.left; 10201 10202 } else { 10203 curTop = parseFloat( curCSSTop ) || 0; 10204 curLeft = parseFloat( curCSSLeft ) || 0; 10205 } 10206 10207 if ( isFunction( options ) ) { 10208 10209 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) 10210 options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); 10211 } 10212 10213 if ( options.top != null ) { 10214 props.top = ( options.top - curOffset.top ) + curTop; 10215 } 10216 if ( options.left != null ) { 10217 props.left = ( options.left - curOffset.left ) + curLeft; 10218 } 10219 10220 if ( "using" in options ) { 10221 options.using.call( elem, props ); 10222 10223 } else { 10224 curElem.css( props ); 10225 } 10226 } 10227}; 10228 10229jQuery.fn.extend( { 10230 10231 // offset() relates an element's border box to the document origin 10232 offset: function( options ) { 10233 10234 // Preserve chaining for setter 10235 if ( arguments.length ) { 10236 return options === undefined ? 10237 this : 10238 this.each( function( i ) { 10239 jQuery.offset.setOffset( this, options, i ); 10240 } ); 10241 } 10242 10243 var rect, win, 10244 elem = this[ 0 ]; 10245 10246 if ( !elem ) { 10247 return; 10248 } 10249 10250 // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 10251 // Support: IE <=11 only 10252 // Running getBoundingClientRect on a 10253 // disconnected node in IE throws an error 10254 if ( !elem.getClientRects().length ) { 10255 return { top: 0, left: 0 }; 10256 } 10257 10258 // Get document-relative position by adding viewport scroll to viewport-relative gBCR 10259 rect = elem.getBoundingClientRect(); 10260 win = elem.ownerDocument.defaultView; 10261 return { 10262 top: rect.top + win.pageYOffset, 10263 left: rect.left + win.pageXOffset 10264 }; 10265 }, 10266 10267 // position() relates an element's margin box to its offset parent's padding box 10268 // This corresponds to the behavior of CSS absolute positioning 10269 position: function() { 10270 if ( !this[ 0 ] ) { 10271 return; 10272 } 10273 10274 var offsetParent, offset, doc, 10275 elem = this[ 0 ], 10276 parentOffset = { top: 0, left: 0 }; 10277 10278 // position:fixed elements are offset from the viewport, which itself always has zero offset 10279 if ( jQuery.css( elem, "position" ) === "fixed" ) { 10280 10281 // Assume position:fixed implies availability of getBoundingClientRect 10282 offset = elem.getBoundingClientRect(); 10283 10284 } else { 10285 offset = this.offset(); 10286 10287 // Account for the *real* offset parent, which can be the document or its root element 10288 // when a statically positioned element is identified 10289 doc = elem.ownerDocument; 10290 offsetParent = elem.offsetParent || doc.documentElement; 10291 while ( offsetParent && 10292 ( offsetParent === doc.body || offsetParent === doc.documentElement ) && 10293 jQuery.css( offsetParent, "position" ) === "static" ) { 10294 10295 offsetParent = offsetParent.parentNode; 10296 } 10297 if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) { 10298 10299 // Incorporate borders into its offset, since they are outside its content origin 10300 parentOffset = jQuery( offsetParent ).offset(); 10301 parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true ); 10302 parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true ); 10303 } 10304 } 10305 10306 // Subtract parent offsets and element margins 10307 return { 10308 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 10309 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) 10310 }; 10311 }, 10312 10313 // This method will return documentElement in the following cases: 10314 // 1) For the element inside the iframe without offsetParent, this method will return 10315 // documentElement of the parent window 10316 // 2) For the hidden or detached element 10317 // 3) For body or html element, i.e. in case of the html node - it will return itself 10318 // 10319 // but those exceptions were never presented as a real life use-cases 10320 // and might be considered as more preferable results. 10321 // 10322 // This logic, however, is not guaranteed and can change at any point in the future 10323 offsetParent: function() { 10324 return this.map( function() { 10325 var offsetParent = this.offsetParent; 10326 10327 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) { 10328 offsetParent = offsetParent.offsetParent; 10329 } 10330 10331 return offsetParent || documentElement; 10332 } ); 10333 } 10334} ); 10335 10336// Create scrollLeft and scrollTop methods 10337jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 10338 var top = "pageYOffset" === prop; 10339 10340 jQuery.fn[ method ] = function( val ) { 10341 return access( this, function( elem, method, val ) { 10342 10343 // Coalesce documents and windows 10344 var win; 10345 if ( isWindow( elem ) ) { 10346 win = elem; 10347 } else if ( elem.nodeType === 9 ) { 10348 win = elem.defaultView; 10349 } 10350 10351 if ( val === undefined ) { 10352 return win ? win[ prop ] : elem[ method ]; 10353 } 10354 10355 if ( win ) { 10356 win.scrollTo( 10357 !top ? val : win.pageXOffset, 10358 top ? val : win.pageYOffset 10359 ); 10360 10361 } else { 10362 elem[ method ] = val; 10363 } 10364 }, method, val, arguments.length ); 10365 }; 10366} ); 10367 10368// Support: Safari <=7 - 9.1, Chrome <=37 - 49 10369// Add the top/left cssHooks using jQuery.fn.position 10370// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 10371// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 10372// getComputedStyle returns percent when specified for top/left/bottom/right; 10373// rather than make the css module depend on the offset module, just check for it here 10374jQuery.each( [ "top", "left" ], function( i, prop ) { 10375 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 10376 function( elem, computed ) { 10377 if ( computed ) { 10378 computed = curCSS( elem, prop ); 10379 10380 // If curCSS returns percentage, fallback to offset 10381 return rnumnonpx.test( computed ) ? 10382 jQuery( elem ).position()[ prop ] + "px" : 10383 computed; 10384 } 10385 } 10386 ); 10387} ); 10388 10389 10390// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 10391jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 10392 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, 10393 function( defaultExtra, funcName ) { 10394 10395 // Margin is only for outerHeight, outerWidth 10396 jQuery.fn[ funcName ] = function( margin, value ) { 10397 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 10398 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 10399 10400 return access( this, function( elem, type, value ) { 10401 var doc; 10402 10403 if ( isWindow( elem ) ) { 10404 10405 // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729) 10406 return funcName.indexOf( "outer" ) === 0 ? 10407 elem[ "inner" + name ] : 10408 elem.document.documentElement[ "client" + name ]; 10409 } 10410 10411 // Get document width or height 10412 if ( elem.nodeType === 9 ) { 10413 doc = elem.documentElement; 10414 10415 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 10416 // whichever is greatest 10417 return Math.max( 10418 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 10419 elem.body[ "offset" + name ], doc[ "offset" + name ], 10420 doc[ "client" + name ] 10421 ); 10422 } 10423 10424 return value === undefined ? 10425 10426 // Get width or height on the element, requesting but not forcing parseFloat 10427 jQuery.css( elem, type, extra ) : 10428 10429 // Set width or height on the element 10430 jQuery.style( elem, type, value, extra ); 10431 }, type, chainable ? margin : undefined, chainable ); 10432 }; 10433 } ); 10434} ); 10435 10436 10437jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + 10438 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 10439 "change select submit keydown keypress keyup contextmenu" ).split( " " ), 10440 function( i, name ) { 10441 10442 // Handle event binding 10443 jQuery.fn[ name ] = function( data, fn ) { 10444 return arguments.length > 0 ? 10445 this.on( name, null, data, fn ) : 10446 this.trigger( name ); 10447 }; 10448} ); 10449 10450jQuery.fn.extend( { 10451 hover: function( fnOver, fnOut ) { 10452 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 10453 } 10454} ); 10455 10456 10457 10458 10459jQuery.fn.extend( { 10460 10461 bind: function( types, data, fn ) { 10462 return this.on( types, null, data, fn ); 10463 }, 10464 unbind: function( types, fn ) { 10465 return this.off( types, null, fn ); 10466 }, 10467 10468 delegate: function( selector, types, data, fn ) { 10469 return this.on( types, selector, data, fn ); 10470 }, 10471 undelegate: function( selector, types, fn ) { 10472 10473 // ( namespace ) or ( selector, types [, fn] ) 10474 return arguments.length === 1 ? 10475 this.off( selector, "**" ) : 10476 this.off( types, selector || "**", fn ); 10477 } 10478} ); 10479 10480// Bind a function to a context, optionally partially applying any 10481// arguments. 10482// jQuery.proxy is deprecated to promote standards (specifically Function#bind) 10483// However, it is not slated for removal any time soon 10484jQuery.proxy = function( fn, context ) { 10485 var tmp, args, proxy; 10486 10487 if ( typeof context === "string" ) { 10488 tmp = fn[ context ]; 10489 context = fn; 10490 fn = tmp; 10491 } 10492 10493 // Quick check to determine if target is callable, in the spec 10494 // this throws a TypeError, but we will just return undefined. 10495 if ( !isFunction( fn ) ) { 10496 return undefined; 10497 } 10498 10499 // Simulated bind 10500 args = slice.call( arguments, 2 ); 10501 proxy = function() { 10502 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 10503 }; 10504 10505 // Set the guid of unique handler to the same of original handler, so it can be removed 10506 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 10507 10508 return proxy; 10509}; 10510 10511jQuery.holdReady = function( hold ) { 10512 if ( hold ) { 10513 jQuery.readyWait++; 10514 } else { 10515 jQuery.ready( true ); 10516 } 10517}; 10518jQuery.isArray = Array.isArray; 10519jQuery.parseJSON = JSON.parse; 10520jQuery.nodeName = nodeName; 10521jQuery.isFunction = isFunction; 10522jQuery.isWindow = isWindow; 10523jQuery.camelCase = camelCase; 10524jQuery.type = toType; 10525 10526jQuery.now = Date.now; 10527 10528jQuery.isNumeric = function( obj ) { 10529 10530 // As of jQuery 3.0, isNumeric is limited to 10531 // strings and numbers (primitives or objects) 10532 // that can be coerced to finite numbers (gh-2662) 10533 var type = jQuery.type( obj ); 10534 return ( type === "number" || type === "string" ) && 10535 10536 // parseFloat NaNs numeric-cast false positives ("") 10537 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 10538 // subtraction forces infinities to NaN 10539 !isNaN( obj - parseFloat( obj ) ); 10540}; 10541 10542 10543 10544 10545// Register as a named AMD module, since jQuery can be concatenated with other 10546// files that may use define, but not via a proper concatenation script that 10547// understands anonymous AMD modules. A named AMD is safest and most robust 10548// way to register. Lowercase jquery is used because AMD module names are 10549// derived from file names, and jQuery is normally delivered in a lowercase 10550// file name. Do this after creating the global so that if an AMD module wants 10551// to call noConflict to hide this version of jQuery, it will work. 10552 10553// Note that for maximum portability, libraries that are not jQuery should 10554// declare themselves as anonymous modules, and avoid setting a global if an 10555// AMD loader is present. jQuery is a special case. For more information, see
vendor: 5,435 bytes, lines 10556-10757
10556// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon 10557 10558if ( typeof define === "function" && define.amd ) { 10559 define( "jquery", [], function() { 10560 return jQuery; 10561 } ); 10562} 10563 10564 10565 10566 10567var 10568 10569 // Map over jQuery in case of overwrite 10570 _jQuery = window.jQuery, 10571 10572 // Map over the $ in case of overwrite 10573 _$ = window.$; 10574 10575jQuery.noConflict = function( deep ) { 10576 if ( window.$ === jQuery ) { 10577 window.$ = _$; 10578 } 10579 10580 if ( deep && window.jQuery === jQuery ) { 10581 window.jQuery = _jQuery; 10582 } 10583 10584 return jQuery; 10585}; 10586 10587// Expose jQuery and $ identifiers, even in AMD 10588// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) 10589// and CommonJS for browser emulators (#13566) 10590if ( !noGlobal ) { 10591 window.jQuery = window.$ = jQuery; 10592} 10593 10594 10595 10596 10597return jQuery; 10598} ); 10599 10600/**! 10601 * @fileOverview Kickass library to create and place poppers near their reference elements. 10602 * @version 1.15.0 10603 * @license 10604 * Copyright (c) 2016 Federico Zivolo and contributors 10605 * 10606 * Permission is hereby granted, free of charge, to any person obtaining a copy 10607 * of this software and associated documentation files (the "Software"), to deal 10608 * in the Software without restriction, including without limitation the rights 10609 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10610 * copies of the Software, and to permit persons to whom the Software is 10611 * furnished to do so, subject to the following conditions: 10612 * 10613 * The above copyright notice and this permission notice shall be included in all 10614 * copies or substantial portions of the Software. 10615 * 10616 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10617 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10618 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10619 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 10620 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10621 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 10622 * SOFTWARE. 10623 */ 10624(function (global, factory) { 10625 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 10626 typeof define === 'function' && define.amd ? define(factory) : 10627 (global.Popper = factory()); 10628}(this, (function () { 'use strict'; 10629 10630var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; 10631 10632var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 10633var timeoutDuration = 0; 10634for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { 10635 if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 10636 timeoutDuration = 1; 10637 break; 10638 } 10639} 10640 10641function microtaskDebounce(fn) { 10642 var called = false; 10643 return function () { 10644 if (called) { 10645 return; 10646 } 10647 called = true; 10648 window.Promise.resolve().then(function () { 10649 called = false; 10650 fn(); 10651 }); 10652 }; 10653} 10654 10655function taskDebounce(fn) { 10656 var scheduled = false; 10657 return function () { 10658 if (!scheduled) { 10659 scheduled = true; 10660 setTimeout(function () { 10661 scheduled = false; 10662 fn(); 10663 }, timeoutDuration); 10664 } 10665 }; 10666} 10667 10668var supportsMicroTasks = isBrowser && window.Promise; 10669 10670/** 10671* Create a debounced version of a method, that's asynchronously deferred 10672* but called in the minimum time possible. 10673* 10674* @method 10675* @memberof Popper.Utils 10676* @argument {Function} fn 10677* @returns {Function} 10678*/ 10679var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce; 10680 10681/** 10682 * Check if the given variable is a function 10683 * @method 10684 * @memberof Popper.Utils 10685 * @argument {Any} functionToCheck - variable to check 10686 * @returns {Boolean} answer to: is a function? 10687 */ 10688function isFunction(functionToCheck) { 10689 var getType = {}; 10690 return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; 10691} 10692 10693/** 10694 * Get CSS computed property of the given element 10695 * @method 10696 * @memberof Popper.Utils 10697 * @argument {Eement} element 10698 * @argument {String} property 10699 */ 10700function getStyleComputedProperty(element, property) { 10701 if (element.nodeType !== 1) { 10702 return []; 10703 } 10704 // NOTE: 1 DOM access here 10705 var window = element.ownerDocument.defaultView; 10706 var css = window.getComputedStyle(element, null); 10707 return property ? css[property] : css; 10708} 10709 10710/** 10711 * Returns the parentNode or the host of the element 10712 * @method 10713 * @memberof Popper.Utils 10714 * @argument {Element} element 10715 * @returns {Element} parent 10716 */ 10717function getParentNode(element) { 10718 if (element.nodeName === 'HTML') { 10719 return element; 10720 } 10721 return element.parentNode || element.host; 10722} 10723 10724/** 10725 * Returns the scrolling parent of the given element 10726 * @method 10727 * @memberof Popper.Utils 10728 * @argument {Element} element 10729 * @returns {Element} scroll parent 10730 */ 10731function getScrollParent(element) { 10732 // Return body, `getScroll` will take care to get the correct `scrollTop` from it 10733 if (!element) { 10734 return document.body; 10735 } 10736 10737 switch (element.nodeName) { 10738 case 'HTML': 10739 case 'BODY': 10740 return element.ownerDocument.body; 10741 case '#document': 10742 return element.body; 10743 } 10744 10745 // Firefox want us to check `-x` and `-y` variations as well 10746 10747 var _getStyleComputedProp = getStyleComputedProperty(element), 10748 overflow = _getStyleComputedProp.overflow, 10749 overflowX = _getStyleComputedProp.overflowX, 10750 overflowY = _getStyleComputedProp.overflowY; 10751 10752 if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { 10753 return element; 10754 } 10755 10756 return getScrollParent(getParentNode(element)); 10757}
vendor: 5,677 bytes, lines 10757-10942
10757 10758 10759var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); 10760var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); 10761 10762/** 10763 * Determines if the browser is Internet Explorer 10764 * @method 10765 * @memberof Popper.Utils 10766 * @param {Number} version to check 10767 * @returns {Boolean} isIE 10768 */ 10769function isIE(version) { 10770 if (version === 11) { 10771 return isIE11; 10772 } 10773 if (version === 10) { 10774 return isIE10; 10775 } 10776 return isIE11 || isIE10; 10777} 10778 10779/** 10780 * Returns the offset parent of the given element 10781 * @method 10782 * @memberof Popper.Utils 10783 * @argument {Element} element 10784 * @returns {Element} offset parent 10785 */ 10786function getOffsetParent(element) { 10787 if (!element) { 10788 return document.documentElement; 10789 } 10790 10791 var noOffsetParent = isIE(10) ? document.body : null; 10792 10793 // NOTE: 1 DOM access here 10794 var offsetParent = element.offsetParent || null; 10795 // Skip hidden elements which don't have an offsetParent 10796 while (offsetParent === noOffsetParent && element.nextElementSibling) { 10797 offsetParent = (element = element.nextElementSibling).offsetParent; 10798 } 10799 10800 var nodeName = offsetParent && offsetParent.nodeName; 10801 10802 if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 10803 return element ? element.ownerDocument.documentElement : document.documentElement; 10804 } 10805 10806 // .offsetParent will return the closest TH, TD or TABLE in case 10807 // no offsetParent is present, I hate this job... 10808 if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { 10809 return getOffsetParent(offsetParent); 10810 } 10811 10812 return offsetParent; 10813} 10814 10815function isOffsetContainer(element) { 10816 var nodeName = element.nodeName; 10817 10818 if (nodeName === 'BODY') { 10819 return false; 10820 } 10821 return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; 10822} 10823 10824/** 10825 * Finds the root node (document, shadowDOM root) of the given element 10826 * @method 10827 * @memberof Popper.Utils 10828 * @argument {Element} node 10829 * @returns {Element} root node 10830 */ 10831function getRoot(node) { 10832 if (node.parentNode !== null) { 10833 return getRoot(node.parentNode); 10834 } 10835 10836 return node; 10837} 10838 10839/** 10840 * Finds the offset parent common to the two provided nodes 10841 * @method 10842 * @memberof Popper.Utils 10843 * @argument {Element} element1 10844 * @argument {Element} element2 10845 * @returns {Element} common offset parent 10846 */ 10847function findCommonOffsetParent(element1, element2) { 10848 // This check is needed to avoid errors in case one of the elements isn't defined for any reason 10849 if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 10850 return document.documentElement; 10851 } 10852 10853 // Here we make sure to give as "start" the element that comes first in the DOM 10854 var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; 10855 var start = order ? element1 : element2; 10856 var end = order ? element2 : element1; 10857 10858 // Get common ancestor container 10859 var range = document.createRange(); 10860 range.setStart(start, 0); 10861 range.setEnd(end, 0); 10862 var commonAncestorContainer = range.commonAncestorContainer; 10863 10864 // Both nodes are inside #document 10865 10866 if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { 10867 if (isOffsetContainer(commonAncestorContainer)) { 10868 return commonAncestorContainer; 10869 } 10870 10871 return getOffsetParent(commonAncestorContainer); 10872 } 10873 10874 // one of the nodes is inside shadowDOM, find which one 10875 var element1root = getRoot(element1); 10876 if (element1root.host) { 10877 return findCommonOffsetParent(element1root.host, element2); 10878 } else { 10879 return findCommonOffsetParent(element1, getRoot(element2).host); 10880 } 10881} 10882 10883/** 10884 * Gets the scroll value of the given element in the given side (top and left) 10885 * @method 10886 * @memberof Popper.Utils 10887 * @argument {Element} element 10888 * @argument {String} side `top` or `left` 10889 * @returns {number} amount of scrolled pixels 10890 */ 10891function getScroll(element) { 10892 var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; 10893 10894 var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 10895 var nodeName = element.nodeName; 10896 10897 if (nodeName === 'BODY' || nodeName === 'HTML') { 10898 var html = element.ownerDocument.documentElement; 10899 var scrollingElement = element.ownerDocument.scrollingElement || html; 10900 return scrollingElement[upperSide]; 10901 } 10902 10903 return element[upperSide]; 10904} 10905 10906/* 10907 * Sum or subtract the element scroll values (left and top) from a given rect object 10908 * @method 10909 * @memberof Popper.Utils 10910 * @param {Object} rect - Rect object you want to change 10911 * @param {HTMLElement} element - The element from the function reads the scroll values 10912 * @param {Boolean} subtract - set to true if you want to subtract the scroll values 10913 * @return {Object} rect - The modifier rect object 10914 */ 10915function includeScroll(rect, element) { 10916 var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; 10917 10918 var scrollTop = getScroll(element, 'top'); 10919 var scrollLeft = getScroll(element, 'left'); 10920 var modifier = subtract ? -1 : 1; 10921 rect.top += scrollTop * modifier; 10922 rect.bottom += scrollTop * modifier; 10923 rect.left += scrollLeft * modifier; 10924 rect.right += scrollLeft * modifier; 10925 return rect; 10926} 10927 10928/* 10929 * Helper to detect borders of a given element 10930 * @method 10931 * @memberof Popper.Utils 10932 * @param {CSSStyleDeclaration} styles 10933 * Result of `getStyleComputedProperty` on the given element 10934 * @param {String} axis - `x` or `y` 10935 * @return {number} borders - The borders size of the given axis 10936 */ 10937 10938function getBordersSize(styles, axis) { 10939 var sideA = axis === 'x' ? 'Left' : 'Top'; 10940 var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 10941 10942 return parseFloat(styles['border' + sideA + 'Width']
vendor: 2,732 bytes, lines 10942-11041
10942, 10) + parseFloat(styles['border' + sideB + 'Width'], 10); 10943} 10944 10945function getSize(axis, body, html, computedStyle) { 10946 return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0); 10947} 10948 10949function getWindowSizes(document) { 10950 var body = document.body; 10951 var html = document.documentElement; 10952 var computedStyle = isIE(10) && getComputedStyle(html); 10953 10954 return { 10955 height: getSize('Height', body, html, computedStyle), 10956 width: getSize('Width', body, html, computedStyle) 10957 }; 10958} 10959 10960var classCallCheck = function (instance, Constructor) { 10961 if (!(instance instanceof Constructor)) { 10962 throw new TypeError("Cannot call a class as a function"); 10963 } 10964}; 10965 10966var createClass = function () { 10967 function defineProperties(target, props) { 10968 for (var i = 0; i < props.length; i++) { 10969 var descriptor = props[i]; 10970 descriptor.enumerable = descriptor.enumerable || false; 10971 descriptor.configurable = true; 10972 if ("value" in descriptor) descriptor.writable = true; 10973 Object.defineProperty(target, descriptor.key, descriptor); 10974 } 10975 } 10976 10977 return function (Constructor, protoProps, staticProps) { 10978 if (protoProps) defineProperties(Constructor.prototype, protoProps); 10979 if (staticProps) defineProperties(Constructor, staticProps); 10980 return Constructor; 10981 }; 10982}(); 10983 10984 10985 10986 10987 10988var defineProperty = function (obj, key, value) { 10989 if (key in obj) { 10990 Object.defineProperty(obj, key, { 10991 value: value, 10992 enumerable: true, 10993 configurable: true, 10994 writable: true 10995 }); 10996 } else { 10997 obj[key] = value; 10998 } 10999 11000 return obj; 11001}; 11002 11003var _extends = Object.assign || function (target) { 11004 for (var i = 1; i < arguments.length; i++) { 11005 var source = arguments[i]; 11006 11007 for (var key in source) { 11008 if (Object.prototype.hasOwnProperty.call(source, key)) { 11009 target[key] = source[key]; 11010 } 11011 } 11012 } 11013 11014 return target; 11015}; 11016 11017/** 11018 * Given element offsets, generate an output similar to getBoundingClientRect 11019 * @method 11020 * @memberof Popper.Utils 11021 * @argument {Object} offsets 11022 * @returns {Object} ClientRect like output 11023 */ 11024function getClientRect(offsets) { 11025 return _extends({}, offsets, { 11026 right: offsets.left + offsets.width, 11027 bottom: offsets.top + offsets.height 11028 }); 11029} 11030 11031/** 11032 * Get bounding client rect of given element 11033 * @method 11034 * @memberof Popper.Utils 11035 * @param {HTMLElement} element 11036 * @return {Object} client rect 11037 */ 11038function getBoundingClientRect(element) { 11039 var rect = {}; 11040 11041 // IE10 10 FIX: Please, don't ask, the element isn't
vendor: 4,668 bytes, lines 11042-11171
11042 // considered in DOM in some circumstances... 11043 // This isn't reproducible in IE10 compatibility mode of IE11 11044 try { 11045 if (isIE(10)) { 11046 rect = element.getBoundingClientRect(); 11047 var scrollTop = getScroll(element, 'top'); 11048 var scrollLeft = getScroll(element, 'left'); 11049 rect.top += scrollTop; 11050 rect.left += scrollLeft; 11051 rect.bottom += scrollTop; 11052 rect.right += scrollLeft; 11053 } else { 11054 rect = element.getBoundingClientRect(); 11055 } 11056 } catch (e) {} 11057 11058 var result = { 11059 left: rect.left, 11060 top: rect.top, 11061 width: rect.right - rect.left, 11062 height: rect.bottom - rect.top 11063 }; 11064 11065 // subtract scrollbar size from sizes 11066 var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {}; 11067 var width = sizes.width || element.clientWidth || result.right - result.left; 11068 var height = sizes.height || element.clientHeight || result.bottom - result.top; 11069 11070 var horizScrollbar = element.offsetWidth - width; 11071 var vertScrollbar = element.offsetHeight - height; 11072 11073 // if an hypothetical scrollbar is detected, we must be sure it's not a `border` 11074 // we make this check conditional for performance reasons 11075 if (horizScrollbar || vertScrollbar) { 11076 var styles = getStyleComputedProperty(element); 11077 horizScrollbar -= getBordersSize(styles, 'x'); 11078 vertScrollbar -= getBordersSize(styles, 'y'); 11079 11080 result.width -= horizScrollbar; 11081 result.height -= vertScrollbar; 11082 } 11083 11084 return getClientRect(result); 11085} 11086 11087function getOffsetRectRelativeToArbitraryNode(children, parent) { 11088 var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; 11089 11090 var isIE10 = isIE(10); 11091 var isHTML = parent.nodeName === 'HTML'; 11092 var childrenRect = getBoundingClientRect(children); 11093 var parentRect = getBoundingClientRect(parent); 11094 var scrollParent = getScrollParent(children); 11095 11096 var styles = getStyleComputedProperty(parent); 11097 var borderTopWidth = parseFloat(styles.borderTopWidth, 10); 11098 var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10); 11099 11100 // In cases where the parent is fixed, we must ignore negative scroll in offset calc 11101 if (fixedPosition && isHTML) { 11102 parentRect.top = Math.max(parentRect.top, 0); 11103 parentRect.left = Math.max(parentRect.left, 0); 11104 } 11105 var offsets = getClientRect({ 11106 top: childrenRect.top - parentRect.top - borderTopWidth, 11107 left: childrenRect.left - parentRect.left - borderLeftWidth, 11108 width: childrenRect.width, 11109 height: childrenRect.height 11110 }); 11111 offsets.marginTop = 0; 11112 offsets.marginLeft = 0; 11113 11114 // Subtract margins of documentElement in case it's being used as parent 11115 // we do this only on HTML because it's the only element that behaves 11116 // differently when margins are applied to it. The margins are included in 11117 // the box of the documentElement, in the other cases not. 11118 if (!isIE10 && isHTML) { 11119 var marginTop = parseFloat(styles.marginTop, 10); 11120 var marginLeft = parseFloat(styles.marginLeft, 10); 11121 11122 offsets.top -= borderTopWidth - marginTop; 11123 offsets.bottom -= borderTopWidth - marginTop; 11124 offsets.left -= borderLeftWidth - marginLeft; 11125 offsets.right -= borderLeftWidth - marginLeft; 11126 11127 // Attach marginTop and marginLeft because in some circumstances we may need them 11128 offsets.marginTop = marginTop; 11129 offsets.marginLeft = marginLeft; 11130 } 11131 11132 if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { 11133 offsets = includeScroll(offsets, parent); 11134 } 11135 11136 return offsets; 11137} 11138 11139function getViewportOffsetRectRelativeToArtbitraryNode(element) { 11140 var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 11141 11142 var html = element.ownerDocument.documentElement; 11143 var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 11144 var width = Math.max(html.clientWidth, window.innerWidth || 0); 11145 var height = Math.max(html.clientHeight, window.innerHeight || 0); 11146 11147 var scrollTop = !excludeScroll ? getScroll(html) : 0; 11148 var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; 11149 11150 var offset = { 11151 top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 11152 left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 11153 width: width, 11154 height: height 11155 }; 11156 11157 return getClientRect(offset); 11158} 11159 11160/** 11161 * Check if the given element is fixed or is inside a fixed parent 11162 * @method 11163 * @memberof Popper.Utils 11164 * @argument {Element} element 11165 * @argument {Element} customContainer 11166 * @returns {Boolean} answer to "isFixed?" 11167 */ 11168function isFixed(element) { 11169 var nodeName = element.nodeName; 11170 if (nodeName === 'BODY' || nodeName === 'HTML') { 11171 return false;
vendor: 9,912 bytes, lines 11172-11479
11172 } 11173 if (getStyleComputedProperty(element, 'position') === 'fixed') { 11174 return true; 11175 } 11176 var parentNode = getParentNode(element); 11177 if (!parentNode) { 11178 return false; 11179 } 11180 return isFixed(parentNode); 11181} 11182 11183/** 11184 * Finds the first parent of an element that has a transformed property defined 11185 * @method 11186 * @memberof Popper.Utils 11187 * @argument {Element} element 11188 * @returns {Element} first transformed parent or documentElement 11189 */ 11190 11191function getFixedPositionOffsetParent(element) { 11192 // This check is needed to avoid errors in case one of the elements isn't defined for any reason 11193 if (!element || !element.parentElement || isIE()) { 11194 return document.documentElement; 11195 } 11196 var el = element.parentElement; 11197 while (el && getStyleComputedProperty(el, 'transform') === 'none') { 11198 el = el.parentElement; 11199 } 11200 return el || document.documentElement; 11201} 11202 11203/** 11204 * Computed the boundaries limits and return them 11205 * @method 11206 * @memberof Popper.Utils 11207 * @param {HTMLElement} popper 11208 * @param {HTMLElement} reference 11209 * @param {number} padding 11210 * @param {HTMLElement} boundariesElement - Element used to define the boundaries 11211 * @param {Boolean} fixedPosition - Is in fixed position mode 11212 * @returns {Object} Coordinates of the boundaries 11213 */ 11214function getBoundaries(popper, reference, padding, boundariesElement) { 11215 var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; 11216 11217 // NOTE: 1 DOM access here 11218 11219 var boundaries = { top: 0, left: 0 }; 11220 var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); 11221 11222 // Handle viewport case 11223 if (boundariesElement === 'viewport') { 11224 boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition); 11225 } else { 11226 // Handle other cases based on DOM element used as boundaries 11227 var boundariesNode = void 0; 11228 if (boundariesElement === 'scrollParent') { 11229 boundariesNode = getScrollParent(getParentNode(reference)); 11230 if (boundariesNode.nodeName === 'BODY') { 11231 boundariesNode = popper.ownerDocument.documentElement; 11232 } 11233 } else if (boundariesElement === 'window') { 11234 boundariesNode = popper.ownerDocument.documentElement; 11235 } else { 11236 boundariesNode = boundariesElement; 11237 } 11238 11239 var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); 11240 11241 // In case of HTML, we need a different computation 11242 if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { 11243 var _getWindowSizes = getWindowSizes(popper.ownerDocument), 11244 height = _getWindowSizes.height, 11245 width = _getWindowSizes.width; 11246 11247 boundaries.top += offsets.top - offsets.marginTop; 11248 boundaries.bottom = height + offsets.top; 11249 boundaries.left += offsets.left - offsets.marginLeft; 11250 boundaries.right = width + offsets.left; 11251 } else { 11252 // for all the other DOM elements, this one is good 11253 boundaries = offsets; 11254 } 11255 } 11256 11257 // Add paddings 11258 padding = padding || 0; 11259 var isPaddingNumber = typeof padding === 'number'; 11260 boundaries.left += isPaddingNumber ? padding : padding.left || 0; 11261 boundaries.top += isPaddingNumber ? padding : padding.top || 0; 11262 boundaries.right -= isPaddingNumber ? padding : padding.right || 0; 11263 boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0; 11264 11265 return boundaries; 11266} 11267 11268function getArea(_ref) { 11269 var width = _ref.width, 11270 height = _ref.height; 11271 11272 return width * height; 11273} 11274 11275/** 11276 * Utility used to transform the `auto` placement to the placement with more 11277 * available space. 11278 * @method 11279 * @memberof Popper.Utils 11280 * @argument {Object} data - The data object generated by update method 11281 * @argument {Object} options - Modifiers configuration and options 11282 * @returns {Object} The data object, properly modified 11283 */ 11284function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { 11285 var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; 11286 11287 if (placement.indexOf('auto') === -1) { 11288 return placement; 11289 } 11290 11291 var boundaries = getBoundaries(popper, reference, padding, boundariesElement); 11292 11293 var rects = { 11294 top: { 11295 width: boundaries.width, 11296 height: refRect.top - boundaries.top 11297 }, 11298 right: { 11299 width: boundaries.right - refRect.right, 11300 height: boundaries.height 11301 }, 11302 bottom: { 11303 width: boundaries.width, 11304 height: boundaries.bottom - refRect.bottom 11305 }, 11306 left: { 11307 width: refRect.left - boundaries.left, 11308 height: boundaries.height 11309 } 11310 }; 11311 11312 var sortedAreas = Object.keys(rects).map(function (key) { 11313 return _extends({ 11314 key: key 11315 }, rects[key], { 11316 area: getArea(rects[key]) 11317 }); 11318 }).sort(function (a, b) { 11319 return b.area - a.area; 11320 }); 11321 11322 var filteredAreas = sortedAreas.filter(function (_ref2) { 11323 var width = _ref2.width, 11324 height = _ref2.height; 11325 return width >= popper.clientWidth && height >= popper.clientHeight; 11326 }); 11327 11328 var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; 11329 11330 var variation = placement.split('-')[1]; 11331 11332 return computedPlacement + (variation ? '-' + variation : ''); 11333} 11334 11335/** 11336 * Get offsets to the reference element 11337 * @method 11338 * @memberof Popper.Utils 11339 * @param {Object} state 11340 * @param {Element} popper - the popper element 11341 * @param {Element} reference - the reference element (the popper will be relative to this) 11342 * @param {Element} fixedPosition - is in fixed position mode 11343 * @returns {Object} An object containing the offsets which will be applied to the popper 11344 */ 11345function getReferenceOffsets(state, popper, reference) { 11346 var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; 11347 11348 var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); 11349 return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); 11350} 11351 11352/** 11353 * Get the outer sizes of the given element (offset size + margins) 11354 * @method 11355 * @memberof Popper.Utils 11356 * @argument {Element} element 11357 * @returns {Object} object containing width and height properties 11358 */ 11359function getOuterSizes(element) { 11360 var window = element.ownerDocument.defaultView; 11361 var styles = window.getComputedStyle(element); 11362 var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0); 11363 var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0); 11364 var result = { 11365 width: element.offsetWidth + y, 11366 height: element.offsetHeight + x 11367 }; 11368 return result; 11369} 11370 11371/** 11372 * Get the opposite placement of the given one 11373 * @method 11374 * @memberof Popper.Utils 11375 * @argument {String} placement 11376 * @returns {String} flipped placement 11377 */ 11378function getOppositePlacement(placement) { 11379 var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 11380 return placement.replace(/left|right|bottom|top/g, function (matched) { 11381 return hash[matched]; 11382 }); 11383} 11384 11385/** 11386 * Get offsets to the popper 11387 * @method 11388 * @memberof Popper.Utils 11389 * @param {Object} position - CSS position the Popper will get applied 11390 * @param {HTMLElement} popper - the popper element 11391 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 11392 * @param {String} placement - one of the valid placement options 11393 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 11394 */ 11395function getPopperOffsets(popper, referenceOffsets, placement) { 11396 placement = placement.split('-')[0]; 11397 11398 // Get popper node sizes 11399 var popperRect = getOuterSizes(popper); 11400 11401 // Add position, width and height to our offsets object 11402 var popperOffsets = { 11403 width: popperRect.width, 11404 height: popperRect.height 11405 }; 11406 11407 // depending by the popper placement we have to compute its offsets slightly differently 11408 var isHoriz = ['right', 'left'].indexOf(placement) !== -1; 11409 var mainSide = isHoriz ? 'top' : 'left'; 11410 var secondarySide = isHoriz ? 'left' : 'top'; 11411 var measurement = isHoriz ? 'height' : 'width'; 11412 var secondaryMeasurement = !isHoriz ? 'height' : 'width'; 11413 11414 popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; 11415 if (placement === secondarySide) { 11416 popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 11417 } else { 11418 popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; 11419 } 11420 11421 return popperOffsets; 11422} 11423 11424/** 11425 * Mimics the `find` method of Array 11426 * @method 11427 * @memberof Popper.Utils 11428 * @argument {Array} arr 11429 * @argument prop 11430 * @argument value 11431 * @returns index or -1 11432 */ 11433function find(arr, check) { 11434 // use native find if supported 11435 if (Array.prototype.find) { 11436 return arr.find(check); 11437 } 11438 11439 // use `filter` to obtain the same behavior of `find` 11440 return arr.filter(check)[0]; 11441} 11442 11443/** 11444 * Return the index of the matching object 11445 * @method 11446 * @memberof Popper.Utils 11447 * @argument {Array} arr 11448 * @argument prop 11449 * @argument value 11450 * @returns index or -1 11451 */ 11452function findIndex(arr, prop, value) { 11453 // use native findIndex if supported 11454 if (Array.prototype.findIndex) { 11455 return arr.findIndex(function (cur) { 11456 return cur[prop] === value; 11457 }); 11458 } 11459 11460 // use `find` + `indexOf` if `findIndex` isn't supported 11461 var match = find(arr, function (obj) { 11462 return obj[prop] === value; 11463 }); 11464 return arr.indexOf(match); 11465} 11466 11467/** 11468 * Loop trough the list of modifiers and run them in order, 11469 * each of them will then edit the data object. 11470 * @method 11471 * @memberof Popper.Utils 11472 * @param {dataObject} data 11473 * @param {Array} modifiers 11474 * @param {String} ends - Optional modifier name used as stopper 11475 * @returns {dataObject} 11476 */ 11477function runModifiers(modifiers, data, ends) { 11478 var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 11479
vendor: 4,062 bytes, lines 11480-11610
11480 modifiersToRun.forEach(function (modifier) { 11481 if (modifier['function']) { 11482 // eslint-disable-line dot-notation 11483 console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 11484 } 11485 var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation 11486 if (modifier.enabled && isFunction(fn)) { 11487 // Add properties to offsets to make them a complete clientRect object 11488 // we do this before each modifier to make sure the previous one doesn't 11489 // mess with these values 11490 data.offsets.popper = getClientRect(data.offsets.popper); 11491 data.offsets.reference = getClientRect(data.offsets.reference); 11492 11493 data = fn(data, modifier); 11494 } 11495 }); 11496 11497 return data; 11498} 11499 11500/** 11501 * Updates the position of the popper, computing the new offsets and applying 11502 * the new style.<br /> 11503 * Prefer `scheduleUpdate` over `update` because of performance reasons. 11504 * @method 11505 * @memberof Popper 11506 */ 11507function update() { 11508 // if popper is destroyed, don't perform any further update 11509 if (this.state.isDestroyed) { 11510 return; 11511 } 11512 11513 var data = { 11514 instance: this, 11515 styles: {}, 11516 arrowStyles: {}, 11517 attributes: {}, 11518 flipped: false, 11519 offsets: {} 11520 }; 11521 11522 // compute reference element offsets 11523 data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); 11524 11525 // compute auto placement, store placement inside the data object, 11526 // modifiers will be able to edit `placement` if needed 11527 // and refer to originalPlacement to know the original value 11528 data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); 11529 11530 // store the computed placement inside `originalPlacement` 11531 data.originalPlacement = data.placement; 11532 11533 data.positionFixed = this.options.positionFixed; 11534 11535 // compute the popper offsets 11536 data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); 11537 11538 data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; 11539 11540 // run the modifiers 11541 data = runModifiers(this.modifiers, data); 11542 11543 // the first `update` will call `onCreate` callback 11544 // the other ones will call `onUpdate` callback 11545 if (!this.state.isCreated) { 11546 this.state.isCreated = true; 11547 this.options.onCreate(data); 11548 } else { 11549 this.options.onUpdate(data); 11550 } 11551} 11552 11553/** 11554 * Helper used to know if the given modifier is enabled. 11555 * @method 11556 * @memberof Popper.Utils 11557 * @returns {Boolean} 11558 */ 11559function isModifierEnabled(modifiers, modifierName) { 11560 return modifiers.some(function (_ref) { 11561 var name = _ref.name, 11562 enabled = _ref.enabled; 11563 return enabled && name === modifierName; 11564 }); 11565} 11566 11567/** 11568 * Get the prefixed supported property name 11569 * @method 11570 * @memberof Popper.Utils 11571 * @argument {String} property (camelCase) 11572 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 11573 */ 11574function getSupportedPropertyName(property) { 11575 var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 11576 var upperProp = property.charAt(0).toUpperCase() + property.slice(1); 11577 11578 for (var i = 0; i < prefixes.length; i++) { 11579 var prefix = prefixes[i]; 11580 var toCheck = prefix ? '' + prefix + upperProp : property; 11581 if (typeof document.body.style[toCheck] !== 'undefined') { 11582 return toCheck; 11583 } 11584 } 11585 return null; 11586} 11587 11588/** 11589 * Destroys the popper. 11590 * @method 11591 * @memberof Popper 11592 */ 11593function destroy() { 11594 this.state.isDestroyed = true; 11595 11596 // touch DOM only if `applyStyle` modifier is enabled 11597 if (isModifierEnabled(this.modifiers, 'applyStyle')) { 11598 this.popper.removeAttribute('x-placement'); 11599 this.popper.style.position = ''; 11600 this.popper.style.top = ''; 11601 this.popper.style.left = ''; 11602 this.popper.style.right = ''; 11603 this.popper.style.bottom = ''; 11604 this.popper.style.willChange = ''; 11605 this.popper.style[getSupportedPropertyName('transform')] = ''; 11606 } 11607 11608 this.disableEventListeners(); 11609 11610 // remove the popper if user explicit
vendor: 15,762 bytes, lines 11610-12059
11610y asked for the deletion on destroy 11611 // do not use `remove` because IE11 doesn't support it 11612 if (this.options.removeOnDestroy) { 11613 this.popper.parentNode.removeChild(this.popper); 11614 } 11615 return this; 11616} 11617 11618/** 11619 * Get the window associated with the element 11620 * @argument {Element} element 11621 * @returns {Window} 11622 */ 11623function getWindow(element) { 11624 var ownerDocument = element.ownerDocument; 11625 return ownerDocument ? ownerDocument.defaultView : window; 11626} 11627 11628function attachToScrollParents(scrollParent, event, callback, scrollParents) { 11629 var isBody = scrollParent.nodeName === 'BODY'; 11630 var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; 11631 target.addEventListener(event, callback, { passive: true }); 11632 11633 if (!isBody) { 11634 attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); 11635 } 11636 scrollParents.push(target); 11637} 11638 11639/** 11640 * Setup needed event listeners used to update the popper position 11641 * @method 11642 * @memberof Popper.Utils 11643 * @private 11644 */ 11645function setupEventListeners(reference, options, state, updateBound) { 11646 // Resize event listener on window 11647 state.updateBound = updateBound; 11648 getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); 11649 11650 // Scroll event listener on scroll parents 11651 var scrollElement = getScrollParent(reference); 11652 attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); 11653 state.scrollElement = scrollElement; 11654 state.eventsEnabled = true; 11655 11656 return state; 11657} 11658 11659/** 11660 * It will add resize/scroll events and start recalculating 11661 * position of the popper element when they are triggered. 11662 * @method 11663 * @memberof Popper 11664 */ 11665function enableEventListeners() { 11666 if (!this.state.eventsEnabled) { 11667 this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); 11668 } 11669} 11670 11671/** 11672 * Remove event listeners used to update the popper position 11673 * @method 11674 * @memberof Popper.Utils 11675 * @private 11676 */ 11677function removeEventListeners(reference, state) { 11678 // Remove resize event listener on window 11679 getWindow(reference).removeEventListener('resize', state.updateBound); 11680 11681 // Remove scroll event listener on scroll parents 11682 state.scrollParents.forEach(function (target) { 11683 target.removeEventListener('scroll', state.updateBound); 11684 }); 11685 11686 // Reset state 11687 state.updateBound = null; 11688 state.scrollParents = []; 11689 state.scrollElement = null; 11690 state.eventsEnabled = false; 11691 return state; 11692} 11693 11694/** 11695 * It will remove resize/scroll events and won't recalculate popper position 11696 * when they are triggered. It also won't trigger `onUpdate` callback anymore, 11697 * unless you call `update` method manually. 11698 * @method 11699 * @memberof Popper 11700 */ 11701function disableEventListeners() { 11702 if (this.state.eventsEnabled) { 11703 cancelAnimationFrame(this.scheduleUpdate); 11704 this.state = removeEventListeners(this.reference, this.state); 11705 } 11706} 11707 11708/** 11709 * Tells if a given input is a number 11710 * @method 11711 * @memberof Popper.Utils 11712 * @param {*} input to check 11713 * @return {Boolean} 11714 */ 11715function isNumeric(n) { 11716 return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 11717} 11718 11719/** 11720 * Set the style to the given popper 11721 * @method 11722 * @memberof Popper.Utils 11723 * @argument {Element} element - Element to apply the style to 11724 * @argument {Object} styles 11725 * Object with a list of properties and values which will be applied to the element 11726 */ 11727function setStyles(element, styles) { 11728 Object.keys(styles).forEach(function (prop) { 11729 var unit = ''; 11730 // add unit if the value is numeric and is one of the following 11731 if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { 11732 unit = 'px'; 11733 } 11734 element.style[prop] = styles[prop] + unit; 11735 }); 11736} 11737 11738/** 11739 * Set the attributes to the given popper 11740 * @method 11741 * @memberof Popper.Utils 11742 * @argument {Element} element - Element to apply the attributes to 11743 * @argument {Object} styles 11744 * Object with a list of properties and values which will be applied to the element 11745 */ 11746function setAttributes(element, attributes) { 11747 Object.keys(attributes).forEach(function (prop) { 11748 var value = attributes[prop]; 11749 if (value !== false) { 11750 element.setAttribute(prop, attributes[prop]); 11751 } else { 11752 element.removeAttribute(prop); 11753 } 11754 }); 11755} 11756 11757/** 11758 * @function 11759 * @memberof Modifiers 11760 * @argument {Object} data - The data object generated by `update` method 11761 * @argument {Object} data.styles - List of style properties - values to apply to popper element 11762 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element 11763 * @argument {Object} options - Modifiers configuration and options 11764 * @returns {Object} The same data object 11765 */ 11766function applyStyle(data) { 11767 // any property present in `data.styles` will be applied to the popper, 11768 // in this way we can make the 3rd party modifiers add custom styles to it 11769 // Be aware, modifiers could override the properties defined in the previous 11770 // lines of this modifier! 11771 setStyles(data.instance.popper, data.styles); 11772 11773 // any property present in `data.attributes` will be applied to the popper, 11774 // they will be set as HTML attributes of the element 11775 setAttributes(data.instance.popper, data.attributes); 11776 11777 // if arrowElement is defined and arrowStyles has some properties 11778 if (data.arrowElement && Object.keys(data.arrowStyles).length) { 11779 setStyles(data.arrowElement, data.arrowStyles); 11780 } 11781 11782 return data; 11783} 11784 11785/** 11786 * Set the x-placement attribute before everything else because it could be used 11787 * to add margins to the popper margins needs to be calculated to get the 11788 * correct popper offsets. 11789 * @method 11790 * @memberof Popper.modifiers 11791 * @param {HTMLElement} reference - The reference element used to position the popper 11792 * @param {HTMLElement} popper - The HTML element used as popper 11793 * @param {Object} options - Popper.js options 11794 */ 11795function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { 11796 // compute reference element offsets 11797 var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); 11798 11799 // compute auto placement, store placement inside the data object, 11800 // modifiers will be able to edit `placement` if needed 11801 // and refer to originalPlacement to know the original value 11802 var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); 11803 11804 popper.setAttribute('x-placement', placement); 11805 11806 // Apply `position` to popper before anything else because 11807 // without the position applied we can't guarantee correct computations 11808 setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' }); 11809 11810 return options; 11811} 11812 11813/** 11814 * @function 11815 * @memberof Popper.Utils 11816 * @argument {Object} data - The data object generated by `update` method 11817 * @argument {Boolean} shouldRound - If the offsets should be rounded at all 11818 * @returns {Object} The popper's position offsets rounded 11819 * 11820 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as 11821 * good as it can be within reason. 11822 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 11823 * 11824 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari 11825 * as well on High DPI screens). 11826 * 11827 * Firefox prefers no rounding for positioning and does not have blurriness on 11828 * high DPI screens. 11829 * 11830 * Only horizontal placement and left/right values need to be considered. 11831 */ 11832function getRoundedOffsets(data, shouldRound) { 11833 var _data$offsets = data.offsets, 11834 popper = _data$offsets.popper, 11835 reference = _data$offsets.reference; 11836 var round = Math.round, 11837 floor = Math.floor; 11838 11839 var noRound = function noRound(v) { 11840 return v; 11841 }; 11842 11843 var referenceWidth = round(reference.width); 11844 var popperWidth = round(popper.width); 11845 11846 var isVertical = ['left', 'right'].indexOf(data.placement) !== -1; 11847 var isVariation = data.placement.indexOf('-') !== -1; 11848 var sameWidthParity = referenceWidth % 2 === popperWidth % 2; 11849 var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; 11850 11851 var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor; 11852 var verticalToInteger = !shouldRound ? noRound : round; 11853 11854 return { 11855 left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left), 11856 top: verticalToInteger(popper.top), 11857 bottom: verticalToInteger(popper.bottom), 11858 right: horizontalToInteger(popper.right) 11859 }; 11860} 11861 11862var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent); 11863 11864/** 11865 * @function 11866 * @memberof Modifiers 11867 * @argument {Object} data - The data object generated by `update` method 11868 * @argument {Object} options - Modifiers configuration and options 11869 * @returns {Object} The data object, properly modified 11870 */ 11871function computeStyle(data, options) { 11872 var x = options.x, 11873 y = options.y; 11874 var popper = data.offsets.popper; 11875 11876 // Remove this legacy support in Popper.js v2 11877 11878 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { 11879 return modifier.name === 'applyStyle'; 11880 }).gpuAcceleration; 11881 if (legacyGpuAccelerationOption !== undefined) { 11882 console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); 11883 } 11884 var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; 11885 11886 var offsetParent = getOffsetParent(data.instance.popper); 11887 var offsetParentRect = getBoundingClientRect(offsetParent); 11888 11889 // Styles 11890 var styles = { 11891 position: popper.position 11892 }; 11893 11894 var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox); 11895 11896 var sideA = x === 'bottom' ? 'top' : 'bottom'; 11897 var sideB = y === 'right' ? 'left' : 'right'; 11898 11899 // if gpuAcceleration is set to `true` and transform is supported, 11900 // we use `translate3d` to apply the position to the popper we 11901 // automatically use the supported prefixed version if needed 11902 var prefixedProperty = getSupportedPropertyName('transform'); 11903 11904 // now, let's make a step back and look at this code closely (wtf?) 11905 // If the content of the popper grows once it's been positioned, it 11906 // may happen that the popper gets misplaced because of the new content 11907 // overflowing its reference element 11908 // To avoid this problem, we provide two options (x and y), which allow 11909 // the consumer to define the offset origin. 11910 // If we position a popper on top of a reference element, we can set 11911 // `x` to `top` to make the popper grow towards its top instead of 11912 // its bottom. 11913 var left = void 0, 11914 top = void 0; 11915 if (sideA === 'bottom') { 11916 // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar) 11917 // and not the bottom of the html element 11918 if (offsetParent.nodeName === 'HTML') { 11919 top = -offsetParent.clientHeight + offsets.bottom; 11920 } else { 11921 top = -offsetParentRect.height + offsets.bottom; 11922 } 11923 } else { 11924 top = offsets.top; 11925 } 11926 if (sideB === 'right') { 11927 if (offsetParent.nodeName === 'HTML') { 11928 left = -offsetParent.clientWidth + offsets.right; 11929 } else { 11930 left = -offsetParentRect.width + offsets.right; 11931 } 11932 } else { 11933 left = offsets.left; 11934 } 11935 if (gpuAcceleration && prefixedProperty) { 11936 styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; 11937 styles[sideA] = 0; 11938 styles[sideB] = 0; 11939 styles.willChange = 'transform'; 11940 } else { 11941 // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties 11942 var invertTop = sideA === 'bottom' ? -1 : 1; 11943 var invertLeft = sideB === 'right' ? -1 : 1; 11944 styles[sideA] = top * invertTop; 11945 styles[sideB] = left * invertLeft; 11946 styles.willChange = sideA + ', ' + sideB; 11947 } 11948 11949 // Attributes 11950 var attributes = { 11951 'x-placement': data.placement 11952 }; 11953 11954 // Update `data` attributes, styles and arrowStyles 11955 data.attributes = _extends({}, attributes, data.attributes); 11956 data.styles = _extends({}, styles, data.styles); 11957 data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles); 11958 11959 return data; 11960} 11961 11962/** 11963 * Helper used to know if the given modifier depends from another one.<br /> 11964 * It checks if the needed modifier is listed and enabled. 11965 * @method 11966 * @memberof Popper.Utils 11967 * @param {Array} modifiers - list of modifiers 11968 * @param {String} requestingName - name of requesting modifier 11969 * @param {String} requestedName - name of requested modifier 11970 * @returns {Boolean} 11971 */ 11972function isModifierRequired(modifiers, requestingName, requestedName) { 11973 var requesting = find(modifiers, function (_ref) { 11974 var name = _ref.name; 11975 return name === requestingName; 11976 }); 11977 11978 var isRequired = !!requesting && modifiers.some(function (modifier) { 11979 return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; 11980 }); 11981 11982 if (!isRequired) { 11983 var _requesting = '`' + requestingName + '`'; 11984 var requested = '`' + requestedName + '`'; 11985 console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); 11986 } 11987 return isRequired; 11988} 11989 11990/** 11991 * @function 11992 * @memberof Modifiers 11993 * @argument {Object} data - The data object generated by update method 11994 * @argument {Object} options - Modifiers configuration and options 11995 * @returns {Object} The data object, properly modified 11996 */ 11997function arrow(data, options) { 11998 var _data$offsets$arrow; 11999 12000 // arrow depends on keepTogether in order to work 12001 if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { 12002 return data; 12003 } 12004 12005 var arrowElement = options.element; 12006 12007 // if arrowElement is a string, suppose it's a CSS selector 12008 if (typeof arrowElement === 'string') { 12009 arrowElement = data.instance.popper.querySelector(arrowElement); 12010 12011 // if arrowElement is not found, don't run the modifier 12012 if (!arrowElement) { 12013 return data; 12014 } 12015 } else { 12016 // if the arrowElement isn't a query selector we must check that the 12017 // provided DOM node is child of its popper node 12018 if (!data.instance.popper.contains(arrowElement)) { 12019 console.warn('WARNING: `arrow.element` must be child of its popper element!'); 12020 return data; 12021 } 12022 } 12023 12024 var placement = data.placement.split('-')[0]; 12025 var _data$offsets = data.offsets, 12026 popper = _data$offsets.popper, 12027 reference = _data$offsets.reference; 12028 12029 var isVertical = ['left', 'right'].indexOf(placement) !== -1; 12030 12031 var len = isVertical ? 'height' : 'width'; 12032 var sideCapitalized = isVertical ? 'Top' : 'Left'; 12033 var side = sideCapitalized.toLowerCase(); 12034 var altSide = isVertical ? 'left' : 'top'; 12035 var opSide = isVertical ? 'bottom' : 'right'; 12036 var arrowElementSize = getOuterSizes(arrowElement)[len]; 12037 12038 // 12039 // extends keepTogether behavior making sure the popper and its 12040 // reference have enough pixels in conjunction 12041 // 12042 12043 // top/left side 12044 if (reference[opSide] - arrowElementSize < popper[side]) { 12045 data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); 12046 } 12047 // bottom/right side 12048 if (reference[side] + arrowElementSize > popper[opSide]) { 12049 data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; 12050 } 12051 data.offsets.popper = getClientRect(data.offsets.popper); 12052 12053 // compute center of the popper 12054 var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; 12055 12056 // Compute the sideValue using the updated popper offsets 12057 // take popper margin in account because we don't have this info available 12058 var css = getStyleComputedProperty(data.instance.popper); 12059 var popperMarginSide = parseFloat(css['margin' + sideCapitalized]
12059, 10); 12060 var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10
vendor: 21,597 bytes, lines 12060-12670
12060); 12061 var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; 12062 12063 // prevent arrowElement from being placed not contiguously to its popper 12064 sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); 12065 12066 data.arrowElement = arrowElement; 12067 data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow); 12068 12069 return data; 12070} 12071 12072/** 12073 * Get the opposite placement variation of the given one 12074 * @method 12075 * @memberof Popper.Utils 12076 * @argument {String} placement variation 12077 * @returns {String} flipped placement variation 12078 */ 12079function getOppositeVariation(variation) { 12080 if (variation === 'end') { 12081 return 'start'; 12082 } else if (variation === 'start') { 12083 return 'end'; 12084 } 12085 return variation; 12086} 12087 12088/** 12089 * List of accepted placements to use as values of the `placement` option.<br /> 12090 * Valid placements are: 12091 * - `auto` 12092 * - `top` 12093 * - `right` 12094 * - `bottom` 12095 * - `left` 12096 * 12097 * Each placement can have a variation from this list: 12098 * - `-start` 12099 * - `-end` 12100 * 12101 * Variations are interpreted easily if you think of them as the left to right 12102 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 12103 * is right.<br /> 12104 * Vertically (`left` and `right`), `start` is top and `end` is bottom. 12105 * 12106 * Some valid examples are: 12107 * - `top-end` (on top of reference, right aligned) 12108 * - `right-start` (on right of reference, top aligned) 12109 * - `bottom` (on bottom, centered) 12110 * - `auto-end` (on the side with more space available, alignment depends by placement) 12111 * 12112 * @static 12113 * @type {Array} 12114 * @enum {String} 12115 * @readonly 12116 * @method placements 12117 * @memberof Popper 12118 */ 12119var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; 12120 12121// Get rid of `auto` `auto-start` and `auto-end` 12122var validPlacements = placements.slice(3); 12123 12124/** 12125 * Given an initial placement, returns all the subsequent placements 12126 * clockwise (or counter-clockwise). 12127 * 12128 * @method 12129 * @memberof Popper.Utils 12130 * @argument {String} placement - A valid placement (it accepts variations) 12131 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 12132 * @returns {Array} placements including their variations 12133 */ 12134function clockwise(placement) { 12135 var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 12136 12137 var index = validPlacements.indexOf(placement); 12138 var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); 12139 return counter ? arr.reverse() : arr; 12140} 12141 12142var BEHAVIORS = { 12143 FLIP: 'flip', 12144 CLOCKWISE: 'clockwise', 12145 COUNTERCLOCKWISE: 'counterclockwise' 12146}; 12147 12148/** 12149 * @function 12150 * @memberof Modifiers 12151 * @argument {Object} data - The data object generated by update method 12152 * @argument {Object} options - Modifiers configuration and options 12153 * @returns {Object} The data object, properly modified 12154 */ 12155function flip(data, options) { 12156 // if `inner` modifier is enabled, we can't use the `flip` modifier 12157 if (isModifierEnabled(data.instance.modifiers, 'inner')) { 12158 return data; 12159 } 12160 12161 if (data.flipped && data.placement === data.originalPlacement) { 12162 // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides 12163 return data; 12164 } 12165 12166 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed); 12167 12168 var placement = data.placement.split('-')[0]; 12169 var placementOpposite = getOppositePlacement(placement); 12170 var variation = data.placement.split('-')[1] || ''; 12171 12172 var flipOrder = []; 12173 12174 switch (options.behavior) { 12175 case BEHAVIORS.FLIP: 12176 flipOrder = [placement, placementOpposite]; 12177 break; 12178 case BEHAVIORS.CLOCKWISE: 12179 flipOrder = clockwise(placement); 12180 break; 12181 case BEHAVIORS.COUNTERCLOCKWISE: 12182 flipOrder = clockwise(placement, true); 12183 break; 12184 default: 12185 flipOrder = options.behavior; 12186 } 12187 12188 flipOrder.forEach(function (step, index) { 12189 if (placement !== step || flipOrder.length === index + 1) { 12190 return data; 12191 } 12192 12193 placement = data.placement.split('-')[0]; 12194 placementOpposite = getOppositePlacement(placement); 12195 12196 var popperOffsets = data.offsets.popper; 12197 var refOffsets = data.offsets.reference; 12198 12199 // using floor because the reference offsets may contain decimals we are not going to consider here 12200 var floor = Math.floor; 12201 var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); 12202 12203 var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); 12204 var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); 12205 var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); 12206 var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); 12207 12208 var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; 12209 12210 // flip the variation if required 12211 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 12212 12213 // flips variation if reference element overflows boundaries 12214 var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); 12215 12216 // flips variation if popper content overflows boundaries 12217 var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop); 12218 12219 var flippedVariation = flippedVariationByRef || flippedVariationByContent; 12220 12221 if (overlapsRef || overflowsBoundaries || flippedVariation) { 12222 // this boolean to detect any flip loop 12223 data.flipped = true; 12224 12225 if (overlapsRef || overflowsBoundaries) { 12226 placement = flipOrder[index + 1]; 12227 } 12228 12229 if (flippedVariation) { 12230 variation = getOppositeVariation(variation); 12231 } 12232 12233 data.placement = placement + (variation ? '-' + variation : ''); 12234 12235 // this object contains `position`, we want to preserve it along with 12236 // any additional property we may add in the future 12237 data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); 12238 12239 data = runModifiers(data.instance.modifiers, data, 'flip'); 12240 } 12241 }); 12242 return data; 12243} 12244 12245/** 12246 * @function 12247 * @memberof Modifiers 12248 * @argument {Object} data - The data object generated by update method 12249 * @argument {Object} options - Modifiers configuration and options 12250 * @returns {Object} The data object, properly modified 12251 */ 12252function keepTogether(data) { 12253 var _data$offsets = data.offsets, 12254 popper = _data$offsets.popper, 12255 reference = _data$offsets.reference; 12256 12257 var placement = data.placement.split('-')[0]; 12258 var floor = Math.floor; 12259 var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 12260 var side = isVertical ? 'right' : 'bottom'; 12261 var opSide = isVertical ? 'left' : 'top'; 12262 var measurement = isVertical ? 'width' : 'height'; 12263 12264 if (popper[side] < floor(reference[opSide])) { 12265 data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; 12266 } 12267 if (popper[opSide] > floor(reference[side])) { 12268 data.offsets.popper[opSide] = floor(reference[side]); 12269 } 12270 12271 return data; 12272} 12273 12274/** 12275 * Converts a string containing value + unit into a px value number 12276 * @function 12277 * @memberof {modifiers~offset} 12278 * @private 12279 * @argument {String} str - Value + unit string 12280 * @argument {String} measurement - `height` or `width` 12281 * @argument {Object} popperOffsets 12282 * @argument {Object} referenceOffsets 12283 * @returns {Number|String} 12284 * Value in pixels, or original string if no values were extracted 12285 */ 12286function toValue(str, measurement, popperOffsets, referenceOffsets) { 12287 // separate value from unit 12288 var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); 12289 var value = +split[1]; 12290 var unit = split[2]; 12291 12292 // If it's not a number it's an operator, I guess 12293 if (!value) { 12294 return str; 12295 } 12296 12297 if (unit.indexOf('%') === 0) { 12298 var element = void 0; 12299 switch (unit) { 12300 case '%p': 12301 element = popperOffsets; 12302 break; 12303 case '%': 12304 case '%r': 12305 default: 12306 element = referenceOffsets; 12307 } 12308 12309 var rect = getClientRect(element); 12310 return rect[measurement] / 100 * value; 12311 } else if (unit === 'vh' || unit === 'vw') { 12312 // if is a vh or vw, we calculate the size based on the viewport 12313 var size = void 0; 12314 if (unit === 'vh') { 12315 size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); 12316 } else { 12317 size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); 12318 } 12319 return size / 100 * value; 12320 } else { 12321 // if is an explicit pixel unit, we get rid of the unit and keep the value 12322 // if is an implicit unit, it's px, and we return just the value 12323 return value; 12324 } 12325} 12326 12327/** 12328 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. 12329 * @function 12330 * @memberof {modifiers~offset} 12331 * @private 12332 * @argument {String} offset 12333 * @argument {Object} popperOffsets 12334 * @argument {Object} referenceOffsets 12335 * @argument {String} basePlacement 12336 * @returns {Array} a two cells array with x and y offsets in numbers 12337 */ 12338function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { 12339 var offsets = [0, 0]; 12340 12341 // Use height if placement is left or right and index is 0 otherwise use width 12342 // in this way the first offset will use an axis and the second one 12343 // will use the other one 12344 var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; 12345 12346 // Split the offset string to obtain a list of values and operands 12347 // The regex addresses values with the plus or minus sign in front (+10, -20, etc) 12348 var fragments = offset.split(/(\+|\-)/).map(function (frag) { 12349 return frag.trim(); 12350 }); 12351 12352 // Detect if the offset string contains a pair of values or a single one 12353 // they could be separated by comma or space 12354 var divider = fragments.indexOf(find(fragments, function (frag) { 12355 return frag.search(/,|\s/) !== -1; 12356 })); 12357 12358 if (fragments[divider] && fragments[divider].indexOf(',') === -1) { 12359 console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); 12360 } 12361 12362 // If divider is found, we divide the list of values and operands to divide 12363 // them by ofset X and Y. 12364 var splitRegex = /\s*,\s*|\s+/; 12365 var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; 12366 12367 // Convert the values with units to absolute pixels to allow our computations 12368 ops = ops.map(function (op, index) { 12369 // Most of the units rely on the orientation of the popper 12370 var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; 12371 var mergeWithPrevious = false; 12372 return op 12373 // This aggregates any `+` or `-` sign that aren't considered operators 12374 // e.g.: 10 + +5 => [10, +, +5] 12375 .reduce(function (a, b) { 12376 if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { 12377 a[a.length - 1] = b; 12378 mergeWithPrevious = true; 12379 return a; 12380 } else if (mergeWithPrevious) { 12381 a[a.length - 1] += b; 12382 mergeWithPrevious = false; 12383 return a; 12384 } else { 12385 return a.concat(b); 12386 } 12387 }, []) 12388 // Here we convert the string values into number values (in px) 12389 .map(function (str) { 12390 return toValue(str, measurement, popperOffsets, referenceOffsets); 12391 }); 12392 }); 12393 12394 // Loop trough the offsets arrays and execute the operations 12395 ops.forEach(function (op, index) { 12396 op.forEach(function (frag, index2) { 12397 if (isNumeric(frag)) { 12398 offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); 12399 } 12400 }); 12401 }); 12402 return offsets; 12403} 12404 12405/** 12406 * @function 12407 * @memberof Modifiers 12408 * @argument {Object} data - The data object generated by update method 12409 * @argument {Object} options - Modifiers configuration and options 12410 * @argument {Number|String} options.offset=0 12411 * The offset value as described in the modifier description 12412 * @returns {Object} The data object, properly modified 12413 */ 12414function offset(data, _ref) { 12415 var offset = _ref.offset; 12416 var placement = data.placement, 12417 _data$offsets = data.offsets, 12418 popper = _data$offsets.popper, 12419 reference = _data$offsets.reference; 12420 12421 var basePlacement = placement.split('-')[0]; 12422 12423 var offsets = void 0; 12424 if (isNumeric(+offset)) { 12425 offsets = [+offset, 0]; 12426 } else { 12427 offsets = parseOffset(offset, popper, reference, basePlacement); 12428 } 12429 12430 if (basePlacement === 'left') { 12431 popper.top += offsets[0]; 12432 popper.left -= offsets[1]; 12433 } else if (basePlacement === 'right') { 12434 popper.top += offsets[0]; 12435 popper.left += offsets[1]; 12436 } else if (basePlacement === 'top') { 12437 popper.left += offsets[0]; 12438 popper.top -= offsets[1]; 12439 } else if (basePlacement === 'bottom') { 12440 popper.left += offsets[0]; 12441 popper.top += offsets[1]; 12442 } 12443 12444 data.popper = popper; 12445 return data; 12446} 12447 12448/** 12449 * @function 12450 * @memberof Modifiers 12451 * @argument {Object} data - The data object generated by `update` method 12452 * @argument {Object} options - Modifiers configuration and options 12453 * @returns {Object} The data object, properly modified 12454 */ 12455function preventOverflow(data, options) { 12456 var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); 12457 12458 // If offsetParent is the reference element, we really want to 12459 // go one step up and use the next offsetParent as reference to 12460 // avoid to make this modifier completely useless and look like broken 12461 if (data.instance.reference === boundariesElement) { 12462 boundariesElement = getOffsetParent(boundariesElement); 12463 } 12464 12465 // NOTE: DOM access here 12466 // resets the popper's position so that the document size can be calculated excluding 12467 // the size of the popper element itself 12468 var transformProp = getSupportedPropertyName('transform'); 12469 var popperStyles = data.instance.popper.style; // assignment to help minification 12470 var top = popperStyles.top, 12471 left = popperStyles.left, 12472 transform = popperStyles[transformProp]; 12473 12474 popperStyles.top = ''; 12475 popperStyles.left = ''; 12476 popperStyles[transformProp] = ''; 12477 12478 var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); 12479 12480 // NOTE: DOM access here 12481 // restores the original style properties after the offsets have been computed 12482 popperStyles.top = top; 12483 popperStyles.left = left; 12484 popperStyles[transformProp] = transform; 12485 12486 options.boundaries = boundaries; 12487 12488 var order = options.priority; 12489 var popper = data.offsets.popper; 12490 12491 var check = { 12492 primary: function primary(placement) { 12493 var value = popper[placement]; 12494 if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { 12495 value = Math.max(popper[placement], boundaries[placement]); 12496 } 12497 return defineProperty({}, placement, value); 12498 }, 12499 secondary: function secondary(placement) { 12500 var mainSide = placement === 'right' ? 'left' : 'top'; 12501 var value = popper[mainSide]; 12502 if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { 12503 value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); 12504 } 12505 return defineProperty({}, mainSide, value); 12506 } 12507 }; 12508 12509 order.forEach(function (placement) { 12510 var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; 12511 popper = _extends({}, popper, check[side](placement)); 12512 }); 12513 12514 data.offsets.popper = popper; 12515 12516 return data; 12517} 12518 12519/** 12520 * @function 12521 * @memberof Modifiers 12522 * @argument {Object} data - The data object generated by `update` method 12523 * @argument {Object} options - Modifiers configuration and options 12524 * @returns {Object} The data object, properly modified 12525 */ 12526function shift(data) { 12527 var placement = data.placement; 12528 var basePlacement = placement.split('-')[0]; 12529 var shiftvariation = placement.split('-')[1]; 12530 12531 // if shift shiftvariation is specified, run the modifier 12532 if (shiftvariation) { 12533 var _data$offsets = data.offsets, 12534 reference = _data$offsets.reference, 12535 popper = _data$offsets.popper; 12536 12537 var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 12538 var side = isVertical ? 'left' : 'top'; 12539 var measurement = isVertical ? 'width' : 'height'; 12540 12541 var shiftOffsets = { 12542 start: defineProperty({}, side, reference[side]), 12543 end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) 12544 }; 12545 12546 data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]); 12547 } 12548 12549 return data; 12550} 12551 12552/** 12553 * @function 12554 * @memberof Modifiers 12555 * @argument {Object} data - The data object generated by update method 12556 * @argument {Object} options - Modifiers configuration and options 12557 * @returns {Object} The data object, properly modified 12558 */ 12559function hide(data) { 12560 if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 12561 return data; 12562 } 12563 12564 var refRect = data.offsets.reference; 12565 var bound = find(data.instance.modifiers, function (modifier) { 12566 return modifier.name === 'preventOverflow'; 12567 }).boundaries; 12568 12569 if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { 12570 // Avoid unnecessary DOM access if visibility hasn't changed 12571 if (data.hide === true) { 12572 return data; 12573 } 12574 12575 data.hide = true; 12576 data.attributes['x-out-of-boundaries'] = ''; 12577 } else { 12578 // Avoid unnecessary DOM access if visibility hasn't changed 12579 if (data.hide === false) { 12580 return data; 12581 } 12582 12583 data.hide = false; 12584 data.attributes['x-out-of-boundaries'] = false; 12585 } 12586 12587 return data; 12588} 12589 12590/** 12591 * @function 12592 * @memberof Modifiers 12593 * @argument {Object} data - The data object generated by `update` method 12594 * @argument {Object} options - Modifiers configuration and options 12595 * @returns {Object} The data object, properly modified 12596 */ 12597function inner(data) { 12598 var placement = data.placement; 12599 var basePlacement = placement.split('-')[0]; 12600 var _data$offsets = data.offsets, 12601 popper = _data$offsets.popper, 12602 reference = _data$offsets.reference; 12603 12604 var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 12605 12606 var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 12607 12608 popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 12609 12610 data.placement = getOppositePlacement(placement); 12611 data.offsets.popper = getClientRect(popper); 12612 12613 return data; 12614} 12615 12616/** 12617 * Modifier function, each modifier can have a function of this type assigned 12618 * to its `fn` property.<br /> 12619 * These functions will be called on each update, this means that you must 12620 * make sure they are performant enough to avoid performance bottlenecks. 12621 * 12622 * @function ModifierFn 12623 * @argument {dataObject} data - The data object generated by `update` method 12624 * @argument {Object} options - Modifiers configuration and options 12625 * @returns {dataObject} The data object, properly modified 12626 */ 12627 12628/** 12629 * Modifiers are plugins used to alter the behavior of your poppers.<br /> 12630 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities 12631 * needed by the library. 12632 * 12633 * Usually you don't want to override the `order`, `fn` and `onLoad` props. 12634 * All the other properties are configurations that could be tweaked. 12635 * @namespace modifiers 12636 */ 12637var modifiers = { 12638 /** 12639 * Modifier used to shift the popper on the start or end of its reference 12640 * element.<br /> 12641 * It will read the variation of the `placement` property.<br /> 12642 * It can be one either `-end` or `-start`. 12643 * @memberof modifiers 12644 * @inner 12645 */ 12646 shift: { 12647 /** @prop {number} order=100 - Index used to define the order of execution */ 12648 order: 100, 12649 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12650 enabled: true, 12651 /** @prop {ModifierFn} */ 12652 fn: shift 12653 }, 12654 12655 /** 12656 * The `offset` modifier can shift your popper on both its axis. 12657 * 12658 * It accepts the following units: 12659 * - `px` or unit-less, interpreted as pixels 12660 * - `%` or `%r`, percentage relative to the length of the reference element 12661 * - `%p`, percentage relative to the length of the popper element 12662 * - `vw`, CSS viewport width unit 12663 * - `vh`, CSS viewport height unit 12664 * 12665 * For length is intended the main axis relative to the placement of the popper.<br /> 12666 * This means that if the placement is `top` or `bottom`, the length will be the 12667 * `width`. In case of `left` or `right`, it will be the `height`. 12668 * 12669 * You can provide a single value (as `Number` or `String`), or a pair of values 12670 * as `String` divided by a comma or one (or more) white space
vendor: 9,957 bytes, lines 12670-12942
12670s.<br /> 12671 * The latter is a deprecated method because it leads to confusion and will be 12672 * removed in v2.<br /> 12673 * Additionally, it accepts additions and subtractions between different units. 12674 * Note that multiplications and divisions aren't supported. 12675 * 12676 * Valid examples are: 12677 * ``` 12678 * 10 12679 * '10%' 12680 * '10, 10' 12681 * '10%, 10' 12682 * '10 + 10%' 12683 * '10 - 5vh + 3%' 12684 * '-10px + 5vh, 5px - 6%' 12685 * ``` 12686 * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap 12687 * > with their reference element, unfortunately, you will have to disable the `flip` modifier. 12688 * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373). 12689 * 12690 * @memberof modifiers 12691 * @inner 12692 */ 12693 offset: { 12694 /** @prop {number} order=200 - Index used to define the order of execution */ 12695 order: 200, 12696 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12697 enabled: true, 12698 /** @prop {ModifierFn} */ 12699 fn: offset, 12700 /** @prop {Number|String} offset=0 12701 * The offset value as described in the modifier description 12702 */ 12703 offset: 0 12704 }, 12705 12706 /** 12707 * Modifier used to prevent the popper from being positioned outside the boundary. 12708 * 12709 * A scenario exists where the reference itself is not within the boundaries.<br /> 12710 * We can say it has "escaped the boundaries" â or just "escaped".<br /> 12711 * In this case we need to decide whether the popper should either: 12712 * 12713 * - detach from the reference and remain "trapped" in the boundaries, or 12714 * - if it should ignore the boundary and "escape with its reference" 12715 * 12716 * When `escapeWithReference` is set to`true` and reference is completely 12717 * outside its boundaries, the popper will overflow (or completely leave) 12718 * the boundaries in order to remain attached to the edge of the reference. 12719 * 12720 * @memberof modifiers 12721 * @inner 12722 */ 12723 preventOverflow: { 12724 /** @prop {number} order=300 - Index used to define the order of execution */ 12725 order: 300, 12726 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12727 enabled: true, 12728 /** @prop {ModifierFn} */ 12729 fn: preventOverflow, 12730 /** 12731 * @prop {Array} [priority=['left','right','top','bottom']] 12732 * Popper will try to prevent overflow following these priorities by default, 12733 * then, it could overflow on the left and on top of the `boundariesElement` 12734 */ 12735 priority: ['left', 'right', 'top', 'bottom'], 12736 /** 12737 * @prop {number} padding=5 12738 * Amount of pixel used to define a minimum distance between the boundaries 12739 * and the popper. This makes sure the popper always has a little padding 12740 * between the edges of its container 12741 */ 12742 padding: 5, 12743 /** 12744 * @prop {String|HTMLElement} boundariesElement='scrollParent' 12745 * Boundaries used by the modifier. Can be `scrollParent`, `window`, 12746 * `viewport` or any DOM element. 12747 */ 12748 boundariesElement: 'scrollParent' 12749 }, 12750 12751 /** 12752 * Modifier used to make sure the reference and its popper stay near each other 12753 * without leaving any gap between the two. Especially useful when the arrow is 12754 * enabled and you want to ensure that it points to its reference element. 12755 * It cares only about the first axis. You can still have poppers with margin 12756 * between the popper and its reference element. 12757 * @memberof modifiers 12758 * @inner 12759 */ 12760 keepTogether: { 12761 /** @prop {number} order=400 - Index used to define the order of execution */ 12762 order: 400, 12763 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12764 enabled: true, 12765 /** @prop {ModifierFn} */ 12766 fn: keepTogether 12767 }, 12768 12769 /** 12770 * This modifier is used to move the `arrowElement` of the popper to make 12771 * sure it is positioned between the reference element and its popper element. 12772 * It will read the outer size of the `arrowElement` node to detect how many 12773 * pixels of conjunction are needed. 12774 * 12775 * It has no effect if no `arrowElement` is provided. 12776 * @memberof modifiers 12777 * @inner 12778 */ 12779 arrow: { 12780 /** @prop {number} order=500 - Index used to define the order of execution */ 12781 order: 500, 12782 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12783 enabled: true, 12784 /** @prop {ModifierFn} */ 12785 fn: arrow, 12786 /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ 12787 element: '[x-arrow]' 12788 }, 12789 12790 /** 12791 * Modifier used to flip the popper's placement when it starts to overlap its 12792 * reference element. 12793 * 12794 * Requires the `preventOverflow` modifier before it in order to work. 12795 * 12796 * **NOTE:** this modifier will interrupt the current update cycle and will 12797 * restart it if it detects the need to flip the placement. 12798 * @memberof modifiers 12799 * @inner 12800 */ 12801 flip: { 12802 /** @prop {number} order=600 - Index used to define the order of execution */ 12803 order: 600, 12804 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12805 enabled: true, 12806 /** @prop {ModifierFn} */ 12807 fn: flip, 12808 /** 12809 * @prop {String|Array} behavior='flip' 12810 * The behavior used to change the popper's placement. It can be one of 12811 * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid 12812 * placements (with optional variations) 12813 */ 12814 behavior: 'flip', 12815 /** 12816 * @prop {number} padding=5 12817 * The popper will flip if it hits the edges of the `boundariesElement` 12818 */ 12819 padding: 5, 12820 /** 12821 * @prop {String|HTMLElement} boundariesElement='viewport' 12822 * The element which will define the boundaries of the popper position. 12823 * The popper will never be placed outside of the defined boundaries 12824 * (except if `keepTogether` is enabled) 12825 */ 12826 boundariesElement: 'viewport', 12827 /** 12828 * @prop {Boolean} flipVariations=false 12829 * The popper will switch placement variation between `-start` and `-end` when 12830 * the reference element overlaps its boundaries. 12831 * 12832 * The original placement should have a set variation. 12833 */ 12834 flipVariations: false, 12835 /** 12836 * @prop {Boolean} flipVariationsByContent=false 12837 * The popper will switch placement variation between `-start` and `-end` when 12838 * the popper element overlaps its reference boundaries. 12839 * 12840 * The original placement should have a set variation. 12841 */ 12842 flipVariationsByContent: false 12843 }, 12844 12845 /** 12846 * Modifier used to make the popper flow toward the inner of the reference element. 12847 * By default, when this modifier is disabled, the popper will be placed outside 12848 * the reference element. 12849 * @memberof modifiers 12850 * @inner 12851 */ 12852 inner: { 12853 /** @prop {number} order=700 - Index used to define the order of execution */ 12854 order: 700, 12855 /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ 12856 enabled: false, 12857 /** @prop {ModifierFn} */ 12858 fn: inner 12859 }, 12860 12861 /** 12862 * Modifier used to hide the popper when its reference element is outside of the 12863 * popper boundaries. It will set a `x-out-of-boundaries` attribute which can 12864 * be used to hide with a CSS selector the popper when its reference is 12865 * out of boundaries. 12866 * 12867 * Requires the `preventOverflow` modifier before it in order to work. 12868 * @memberof modifiers 12869 * @inner 12870 */ 12871 hide: { 12872 /** @prop {number} order=800 - Index used to define the order of execution */ 12873 order: 800, 12874 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12875 enabled: true, 12876 /** @prop {ModifierFn} */ 12877 fn: hide 12878 }, 12879 12880 /** 12881 * Computes the style that will be applied to the popper element to gets 12882 * properly positioned. 12883 * 12884 * Note that this modifier will not touch the DOM, it just prepares the styles 12885 * so that `applyStyle` modifier can apply it. This separation is useful 12886 * in case you need to replace `applyStyle` with a custom implementation. 12887 * 12888 * This modifier has `850` as `order` value to maintain backward compatibility 12889 * with previous versions of Popper.js. Expect the modifiers ordering method 12890 * to change in future major versions of the library. 12891 * 12892 * @memberof modifiers 12893 * @inner 12894 */ 12895 computeStyle: { 12896 /** @prop {number} order=850 - Index used to define the order of execution */ 12897 order: 850, 12898 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12899 enabled: true, 12900 /** @prop {ModifierFn} */ 12901 fn: computeStyle, 12902 /** 12903 * @prop {Boolean} gpuAcceleration=true 12904 * If true, it uses the CSS 3D transformation to position the popper. 12905 * Otherwise, it will use the `top` and `left` properties 12906 */ 12907 gpuAcceleration: true, 12908 /** 12909 * @prop {string} [x='bottom'] 12910 * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. 12911 * Change this if your popper should grow in a direction different from `bottom` 12912 */ 12913 x: 'bottom', 12914 /** 12915 * @prop {string} [x='left'] 12916 * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. 12917 * Change this if your popper should grow in a direction different from `right` 12918 */ 12919 y: 'right' 12920 }, 12921 12922 /** 12923 * Applies the computed styles to the popper element. 12924 * 12925 * All the DOM manipulations are limited to this modifier. This is useful in case 12926 * you want to integrate Popper.js inside a framework or view library and you 12927 * want to delegate all the DOM manipulations to it. 12928 * 12929 * Note that if you disable this modifier, you must make sure the popper element 12930 * has its position set to `absolute` before Popper.js can do its work! 12931 * 12932 * Just disable this modifier and define your own to achieve the desired effect. 12933 * 12934 * @memberof modifiers 12935 * @inner 12936 */ 12937 applyStyle: { 12938 /** @prop {number} order=900 - Index used to define the order of execution */ 12939 order: 900, 12940 /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ 12941 enabled: true, 12942 /** @prop {ModifierFn} */
vendor: 9,127 bytes, lines 12943-13207
12943 fn: applyStyle, 12944 /** @prop {Function} */ 12945 onLoad: applyStyleOnLoad, 12946 /** 12947 * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier 12948 * @prop {Boolean} gpuAcceleration=true 12949 * If true, it uses the CSS 3D transformation to position the popper. 12950 * Otherwise, it will use the `top` and `left` properties 12951 */ 12952 gpuAcceleration: undefined 12953 } 12954}; 12955 12956/** 12957 * The `dataObject` is an object containing all the information used by Popper.js. 12958 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks. 12959 * @name dataObject 12960 * @property {Object} data.instance The Popper.js instance 12961 * @property {String} data.placement Placement applied to popper 12962 * @property {String} data.originalPlacement Placement originally defined on init 12963 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier 12964 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper 12965 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier 12966 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`) 12967 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`) 12968 * @property {Object} data.boundaries Offsets of the popper boundaries 12969 * @property {Object} data.offsets The measurements of popper, reference and arrow elements 12970 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values 12971 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values 12972 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 12973 */ 12974 12975/** 12976 * Default options provided to Popper.js constructor.<br /> 12977 * These can be overridden using the `options` argument of Popper.js.<br /> 12978 * To override an option, simply pass an object with the same 12979 * structure of the `options` object, as the 3rd argument. For example: 12980 * ``` 12981 * new Popper(ref, pop, { 12982 * modifiers: { 12983 * preventOverflow: { enabled: false } 12984 * } 12985 * }) 12986 * ``` 12987 * @type {Object} 12988 * @static 12989 * @memberof Popper 12990 */ 12991var Defaults = { 12992 /** 12993 * Popper's placement. 12994 * @prop {Popper.placements} placement='bottom' 12995 */ 12996 placement: 'bottom', 12997 12998 /** 12999 * Set this to true if you want popper to position it self in 'fixed' mode 13000 * @prop {Boolean} positionFixed=false 13001 */ 13002 positionFixed: false, 13003 13004 /** 13005 * Whether events (resize, scroll) are initially enabled. 13006 * @prop {Boolean} eventsEnabled=true 13007 */ 13008 eventsEnabled: true, 13009 13010 /** 13011 * Set to true if you want to automatically remove the popper when 13012 * you call the `destroy` method. 13013 * @prop {Boolean} removeOnDestroy=false 13014 */ 13015 removeOnDestroy: false, 13016 13017 /** 13018 * Callback called when the popper is created.<br /> 13019 * By default, it is set to no-op.<br /> 13020 * Access Popper.js instance with `data.instance`. 13021 * @prop {onCreate} 13022 */ 13023 onCreate: function onCreate() {}, 13024 13025 /** 13026 * Callback called when the popper is updated. This callback is not called 13027 * on the initialization/creation of the popper, but only on subsequent 13028 * updates.<br /> 13029 * By default, it is set to no-op.<br /> 13030 * Access Popper.js instance with `data.instance`. 13031 * @prop {onUpdate} 13032 */ 13033 onUpdate: function onUpdate() {}, 13034 13035 /** 13036 * List of modifiers used to modify the offsets before they are applied to the popper. 13037 * They provide most of the functionalities of Popper.js. 13038 * @prop {modifiers} 13039 */ 13040 modifiers: modifiers 13041}; 13042 13043/** 13044 * @callback onCreate 13045 * @param {dataObject} data 13046 */ 13047 13048/** 13049 * @callback onUpdate 13050 * @param {dataObject} data 13051 */ 13052 13053// Utils 13054// Methods 13055var Popper = function () { 13056 /** 13057 * Creates a new Popper.js instance. 13058 * @class Popper 13059 * @param {Element|referenceObject} reference - The reference element used to position the popper 13060 * @param {Element} popper - The HTML / XML element used as the popper 13061 * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) 13062 * @return {Object} instance - The generated Popper.js instance 13063 */ 13064 function Popper(reference, popper) { 13065 var _this = this; 13066 13067 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 13068 classCallCheck(this, Popper); 13069 13070 this.scheduleUpdate = function () { 13071 return requestAnimationFrame(_this.update); 13072 }; 13073 13074 // make update() debounced, so that it only runs at most once-per-tick 13075 this.update = debounce(this.update.bind(this)); 13076 13077 // with {} we create a new object with the options inside it 13078 this.options = _extends({}, Popper.Defaults, options); 13079 13080 // init state 13081 this.state = { 13082 isDestroyed: false, 13083 isCreated: false, 13084 scrollParents: [] 13085 }; 13086 13087 // get reference and popper elements (allow jQuery wrappers) 13088 this.reference = reference && reference.jquery ? reference[0] : reference; 13089 this.popper = popper && popper.jquery ? popper[0] : popper; 13090 13091 // Deep merge modifiers options 13092 this.options.modifiers = {}; 13093 Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { 13094 _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); 13095 }); 13096 13097 // Refactoring modifiers' list (Object => Array) 13098 this.modifiers = Object.keys(this.options.modifiers).map(function (name) { 13099 return _extends({ 13100 name: name 13101 }, _this.options.modifiers[name]); 13102 }) 13103 // sort the modifiers by order 13104 .sort(function (a, b) { 13105 return a.order - b.order; 13106 }); 13107 13108 // modifiers have the ability to execute arbitrary code when Popper.js get inited 13109 // such code is executed in the same order of its modifier 13110 // they could add new properties to their options configuration 13111 // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! 13112 this.modifiers.forEach(function (modifierOptions) { 13113 if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { 13114 modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); 13115 } 13116 }); 13117 13118 // fire the first update to position the popper in the right place 13119 this.update(); 13120 13121 var eventsEnabled = this.options.eventsEnabled; 13122 if (eventsEnabled) { 13123 // setup event listeners, they will take care of update the position in specific situations 13124 this.enableEventListeners(); 13125 } 13126 13127 this.state.eventsEnabled = eventsEnabled; 13128 } 13129 13130 // We can't use class properties because they don't get listed in the 13131 // class prototype and break stuff like Sinon stubs 13132 13133 13134 createClass(Popper, [{ 13135 key: 'update', 13136 value: function update$$1() { 13137 return update.call(this); 13138 } 13139 }, { 13140 key: 'destroy', 13141 value: function destroy$$1() { 13142 return destroy.call(this); 13143 } 13144 }, { 13145 key: 'enableEventListeners', 13146 value: function enableEventListeners$$1() { 13147 return enableEventListeners.call(this); 13148 } 13149 }, { 13150 key: 'disableEventListeners', 13151 value: function disableEventListeners$$1() { 13152 return disableEventListeners.call(this); 13153 } 13154 13155 /** 13156 * Schedules an update. It will run on the next UI update available. 13157 * @method scheduleUpdate 13158 * @memberof Popper 13159 */ 13160 13161 13162 /** 13163 * Collection of utilities useful when writing custom modifiers. 13164 * Starting from version 1.7, this method is available only if you 13165 * include `popper-utils.js` before `popper.js`. 13166 * 13167 * **DEPRECATION**: This way to access PopperUtils is deprecated 13168 * and will be removed in v2! Use the PopperUtils module directly instead. 13169 * Due to the high instability of the methods contained in Utils, we can't 13170 * guarantee them to follow semver. Use them at your own risk! 13171 * @static 13172 * @private 13173 * @type {Object} 13174 * @deprecated since version 1.8 13175 * @member Utils 13176 * @memberof Popper 13177 */ 13178 13179 }]); 13180 return Popper; 13181}(); 13182 13183/** 13184 * The `referenceObject` is an object that provides an interface compatible with Popper.js 13185 * and lets you use it as replacement of a real DOM node.<br /> 13186 * You can use this method to position a popper relatively to a set of coordinates 13187 * in case you don't have a DOM node to use as reference. 13188 * 13189 * ``` 13190 * new Popper(referenceObject, popperNode); 13191 * ``` 13192 * 13193 * NB: This feature isn't supported in Internet Explorer 10. 13194 * @name referenceObject 13195 * @property {Function} data.getBoundingClientRect 13196 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. 13197 * @property {number} data.clientWidth 13198 * An ES6 getter that will return the width of the virtual reference element. 13199 * @property {number} data.clientHeight 13200 * An ES6 getter that will return the height of the virtual reference element. 13201 */ 13202 13203 13204Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; 13205Popper.placements = placements; 13206Popper.Defaults = Defaults; 13207
13208return Popper; 13209 13210}))); 13211//# sourceMappingURL=popper.js.map 13212 13213/*! 13214 * Bootstrap v4.3.1 (https://getbootstrap.com/) 13215 * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) 13216 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 13217 */ 13218!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function s(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}function l(o){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{},e=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),e.forEach(function(t){var e,n,i;e=o,i=r[n=t],n in e?Object.defineProperty(e,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[n]=i})}return o}g=g&&g.hasOwnProperty("default")?g.default:g,u=u&&u.hasOwnProperty("default")?u.default:u;var e="transitionend";function n(t){var e=this,n=!1;return g(this).one(_.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||_.triggerTransitionEnd(e)},t),this}var _={TRANSITION_END:"bsTransitionEnd",getUID:function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(t){if(!t)return 0;var e=g(t).css("transition-duration"),n=g(t).css("transition-delay"),i=parseFloat(e),o=parseFloat(n);return i||o?(e=e.split(",")[0],n=n.split(",")[0],1e3*(parseFloat(e)+parseFloat(n))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(t){g(t).trigger(e)},supportsTransitionEnd:function(){return Boolean(e)},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var o=n[i],r=e[i],s=r&&_.isElement(r)?"element":(a=r,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(o).test(s))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+o+'".')}var a},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"!=typeof t.getRootNode)return t instanceof ShadowRoot?t:t.parentNode?_.findShadowRoot(t.parentNode):null;var e=t.getRootNode();return e instanceof ShadowRoot?e:null}};g.fn.emulateTransitionEnd=n,g.event.special[_.TRANSITION_END]={bindType:e,delegateType:e,handle:function(t){if(g(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var o="alert",r="bs.alert",a="."+r,c=g.fn[o],h={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",d="fade",m="show",p=function(){function i(t){this._element=t}var t=i.prototype;return t.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)}
13218,t.dispose=function(){g.removeData(this._element,r),this._element=null},t._getRootElement=function(t){var e=_.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=g(t).closest("."+f)[0]),n},t._triggerCloseEvent=function(t){var e=g.Event(h.CLOSE);return g(t).trigger(e),e},t._removeElement=function(e){var n=this;if(g(e).removeClass(m),g(e).hasClass(d)){var t=_.getTransitionDurationFromElement(e);g(e).one(_.TRANSITION_END,function(t){return n._destroyElement(e,t)}).emulateTransitionEnd(t)}else this._destroyElement(e)},t._destroyElement=function(t){g(t).detach().trigger(h.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(r);e||(e=new i(this),t.data(r,e)),"close"===n&&e[n](this)})},i._handleDismiss=function(e){return function(t){t&&t.preventDefault(),e.close(this)}},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(h.CLICK_DATA_API,'[data-dismiss="alert"]',p._handleDismiss(new p)),g.fn[o]=p._jQueryInterface,g.fn[o].Constructor=p,g.fn[o].noConflict=function(){return g.fn[o]=c,p._jQueryInterface};var v="button",y="bs.button",E="."+y,C=".data-api",T=g.fn[v],S="active",b="btn",I="focus",D='[data-toggle^="button"]',w='[data-toggle="buttons"]',A='input:not([type="hidden"])',N=".active",O=".btn",k={CLICK_DATA_API:"click"+E+C,FOCUS_BLUR_DATA_API:"focus"+E+C+" blur"+E+C},P=function(){function n(t){this._element=t}var t=n.prototype;return t.toggle=function(){var t=!0,e=!0,n=g(this._element).closest(w)[0];if(n){var i=this._element.querySelector(A);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(S))t=!1;else{var o=n.querySelector(N);o&&g(o).removeClass(S)}if(t){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!this._element.classList.contains(S),g(i).trigger("change")}i.focus(),e=!1}}e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(S)),t&&g(this._element).toggleClass(S)},t.dispose=function(){g.removeData(this._element,y),this._element=null},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(y);t||(t=new n(this),g(this).data(y,t)),"toggle"===e&&t[e]()})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),n}();g(document).on(k.CLICK_DATA_API,D,function(t){t.preventDefault();var e=t.target;g(e).hasClass(b)||(e=g(e).closest(O)),P._jQueryInterface.call(g(e),"toggle")}).on(k.FOCUS_BLUR_DATA_API,D,function(t){var e=g(t.target).closest(O)[0];g(e).toggleClass(I,/^focus(in)?$/.test(t.type))}),g.fn[v]=P._jQueryInterface,g.fn[v].Constructor=P,g.fn[v].noConflict=function(){return g.fn[v]=T,P._jQueryInterface};var L="carousel",j="bs.carousel",H="."+j,R=".data-api",x=g.fn[L],F={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},U={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},W="next",q="prev",M="left",K="right",Q={SLIDE:"slide"+H,SLID:"slid"+H,KEYDOWN:"keydown"+H,MOUSEENTER:"mouseenter"+H,MOUSELEAVE:"mouseleave"+H,TOUCHSTART:"touchstart"+H,TOUCHMOVE:"touchmove"+H,TOUCHEND:"touchend"+H,POINTERDOWN:"pointerdown"+H,POINTERUP:"pointerup"+H,DRAG_START:"dragstart"+H,LOAD_DATA_API:"load"+H+R,CLICK_DATA_API:"click"+H+R},B="carousel",V="active",Y="slide",z="carousel-item-right",X="carousel-item-left",$="carousel-item-next",G="carousel-item-prev",J="pointer-event",Z=".active",tt=".active.carousel-item",et=".carousel-item",nt=".carousel-item img",it=".carousel-item-next, .carousel-item-prev",ot=".carousel-indicators",rt="[data-slide], [data-slide-to]",st='[data-ride="carousel"]',at={TOUCH:"touch",PEN:"pen"},lt=function(){function r(t,e){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._element=t,this._indicatorsElement=this._element.querySelector(ot),this._touchSupported="ontouchstart"in document.documentElement||0<navigator.maxTouchPoints,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var t=r.prototype;return t.next=function(){this._isSliding||this._slide(W)},t.nextWhenVisible=function(){!document.hidden&&g(this._element).is(":visible")&&"hidden"
13218!==g(this._element).css("visibility")&&this.next()},t.prev=function(){this._isSliding||this._slide(q)},t.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(it)&&(_.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},t.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},t.to=function(t){var e=this;this._activeElement=this._element.querySelector(tt);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=n<t?W:q;this._slide(i,this._items[t])}},t.dispose=function(){g(this._element).off(H),g.removeData(this._element,j),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},t._getConfig=function(t){return t=l({},F,t),_.typeCheckConfig(L,t,U),t},t._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;0<e&&this.prev(),e<0&&this.next()}},t._addEventListeners=function(){var e=this;this._config.keyboard&&g(this._element).on(Q.KEYDOWN,function(t){return e._keydown(t)}),"hover"===this._config.pause&&g(this._element).on(Q.MOUSEENTER,function(t){return e.pause(t)}).on(Q.MOUSELEAVE,function(t){return e.cycle(t)}),this._config.touch&&this._addTouchEventListeners()},t._addTouchEventListeners=function(){var n=this;if(this._touchSupported){var e=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]?n.touchStartX=t.originalEvent.clientX:n._pointerEvent||(n.touchStartX=t.originalEvent.touches[0].clientX)},i=function(t){n._pointerEvent&&at[t.originalEvent.pointerType.toUpperCase()]&&(n.touchDeltaX=t.originalEvent.clientX-n.touchStartX),n._handleSwipe(),"hover"===n._config.pause&&(n.pause(),n.touchTimeout&&clearTimeout(n.touchTimeout),n.touchTimeout=setTimeout(function(t){return n.cycle(t)},500+n._config.interval))};g(this._element.querySelectorAll(nt)).on(Q.DRAG_START,function(t){return t.preventDefault()}),this._pointerEvent?(g(this._element).on(Q.POINTERDOWN,function(t){return e(t)}),g(this._element).on(Q.POINTERUP,function(t){return i(t)}),this._element.classList.add(J)):(g(this._element).on(Q.TOUCHSTART,function(t){return e(t)}),g(this._element).on(Q.TOUCHMOVE,function(t){var e;(e=t).originalEvent.touches&&1<e.originalEvent.touches.length?n.touchDeltaX=0:n.touchDeltaX=e.originalEvent.touches[0].clientX-n.touchStartX}),g(this._element).on(Q.TOUCHEND,function(t){return i(t)}))}},t._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},t._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(et)):[],this._items.indexOf(t)},t._getItemByDirection=function(t,e){var n=t===W,i=t===q,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+(t===q?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},t._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(tt)),o=g.Event(Q.SLIDE,{relatedTarget:t,direction:e,from:i,to:n});return g(this._element).trigger(o),o},t._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(Z));g(e).removeClass(V);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&g(n).addClass(V)}},t._slide=function(t,e){var n,i,o,r=this,s=this._element.querySelector(tt),a=this._getItemIndex(s),l=e||s&&this._getItemByDirection(t,s),c=this._getItemIndex(l),h=Boolean(this._interval);if(o=t===W?(n=X,i=$,M):(n=z,i=G,K),l&&g(l).hasClass(V))this._isSliding=!1;else if(!this._triggerSlideEvent(l,o).isDefaultPrevented()&&s&&l){this._isSliding=!0,h&&this.pause(),this._setActiveIndicatorElement(l);var u=g.Event(Q.SLID,{relatedTarget:l,direction:o,from:a,to:c});if(g(this._element).hasClass(Y)){g(l).addClass(i),_.reflow(l),g(s).addClass(n),g(l).addClass(n);var f=parseInt(l.getAttribute("data-interval"),10);this._config.interval=f?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,f):this._config.defaultInterval||this._config.interval;var d=_.getTransitionDurationFromElement(s);g(s).one(_.TRANSITION_END,function(){g(l).removeClass(n+" "+i).addClass(V),g(s).removeClass(V+" "+i+" "+n),r._isSliding=!1,setTimeout(function(){return g(r._element).trigger(u)},0)}).emulateTransitionEnd(d)}else g(s).removeClass(V),g(l).addClass(V),this._isSliding=!1,g(this._element).trigger(u);h&&this.cycle()}},r._jQueryInterface=function(i){return this.each(function(){var t=g(this).data(j),e=l({},F,g(this).data());"object"==typeof i&&(e=l({},e,i));var n="string"==typeof i?i:e.slide;if(t||(t=new r(this,e),g(this).data(j,t)),"number"==typeof i)t.to(i);else if("string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n]()}else e.interval&&e.ride&&(t.pause(),t.cycle())})},r._dataApiClickHandler=function(t){var e=_.getSelectorFromElement(this);if(e){var n=g(e)[0];if(n&&g(n).hasClass(B)){var i=l({},g(n).data(),g(this).data()),o=this.getAttribute("data-slide-to");o&&(i.interval=!1),r._jQueryInterface.call(g(n),i),o&&g(n).data(j).to(o),t.preventDefault()}}},s(r,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return F}}]),r}();g(document).on(Q.CLICK_DATA_API,rt,lt._dataApiClickHandler),g(window).on(Q.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(st)),e=0,n=t.length;e<n;e++){var i=g(t[e]);lt._jQueryInterface.call(i,i.data())}}),g.fn[L]=lt._jQueryInterface,g.fn[L].Constructor=lt,g.fn[L].noConflict=function(){return g.fn[L]=x,lt._jQueryInterface};var ct="collapse",ht="bs.collapse",ut="."+ht,ft=g.fn[ct],dt={toggle:!0,parent:""},gt={toggle:"boolean",parent:"(string|element)"},_t={SHOW:"show"+ut,SHOWN:"shown"+ut,HIDE:"hide"+ut,HIDDEN:"hidden"+ut,CLICK_DATA_API:"click"+ut+".data-api"},mt="show",pt="collapse",vt="collapsing",yt="collapsed",Et="width",Ct="height",Tt=".show, .collapsing",St='[data-toggle="collapse"]',bt=function(){function a(e,t){this._isTransitioning=!1,this._element=e,this._config=this._getConfig(t),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'));for(var n=[].slice.call(document.querySelectorAll(St)),i=0,o=n.length;i<o;i++){var r=n[i],s=_.getSelectorFromElement(r),a=[].slice.call(document.querySelectorAll(s)).filter(function(t){return t===e});null!==s&&0<a.length&&(this._selector=s,this._triggerArray.push(r))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var t=a.prototype;return t.toggle=function(){g(this._element).hasClass(mt)?this.hide():this.show()},t.show=function(){var t,e,n=this;if(!this._isTransitioning&&!g(this._element).hasClass(mt)&&(this._parent&&0===(t=[].slice.call(this._parent.querySelectorAll(Tt)).filter(function(t){return"string"==typeof n._config.parent?t.getAttribute("data-parent")===n._config.parent:t.classList.contains(pt)})).length&&(t=null),!(t&&(e=g(t).not(this._selector).data(ht))&&e._isTransitioning))){var i=g.Event(_t.SHOW);if(g(this._element).trigger(i),!i.isDefaultPrevented()){t&&(a._jQueryInterface.call(g(t).not(this._selector),"hide"),e||g(t).data(ht,null));var o=this._getDimension();g(this._element).removeClass(pt).addClass(vt),this._element.style[o]=0,this._triggerArray.length&&g(this._triggerArray).removeClass(yt).attr("aria-expanded",!0),this.setTransitioning(!0);var r="scroll"+(o[0].toUpperCase()+o.slice(1)),s=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){g(n._element).removeClass(vt).addClass(pt).addClass(mt),n._element.style[o]="",n.setTransitioning(!1),g(n._element).trigger(_t.SHOWN)}).emulateTransitionEnd(s),this._element.style[o]=this._element[r]+"px"}}},t.hide=function(){var t=this;if(!this._isTransitioning&&g(this._element).hasClass(mt)){var e=g.Event(_t.HIDE);if(g(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",_.reflow(this._element),g(this._element).addClass(vt).removeClass(pt).removeClass(mt);var i=this._triggerArray.length;if(0<i)for(var o=0;o<i;o++){var r=this._triggerArray[o],s=_.getSelectorFromElement(r);if(null!==s)g([].slice.call(document.querySelectorAll(s))).hasClass(mt)||g(r).addClass(yt).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var a=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(){t.setTransitioning(!1),g(t._element).removeClass(vt).addClass(pt).trigger(_t.HIDDEN)}).emulateTransitionEnd(a)}}},t.setTransitioning=function(t){this._isTransitioning=t},t.dispose=function(){g.removeData(this._element,ht),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},t._getConfig=function(t){return(t=l({},dt,t)).toggle=Boolean(t.toggle),_.typeCheckConfig(ct,t,gt),t},t._getDimension=function(){return g(this._element).hasClass(Et)?Et:Ct},t._getParent=function(){var t,n=this;_.isElement(this._config.parent)?(t=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(t=this._config.parent[0])):t=document.querySelector(this._config.parent);var e='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',i=[].slice.call(t.querySelectorAll(e));return g(i).each(function(t,e){n._addAriaAndCollapsedClass(a._getTargetFromElement(e),[e])}),t},t._addAriaAndCollapsedClass=function(t,e){var n=g(t).hasClass(mt);e.length&&g(e).toggleClass(yt,!n).attr("aria-expanded",n)},a._getTargetFromElement=function(t){var e=_.getSelectorFromElement(t);return e?document.querySelector(e):null},a._jQueryInterface=function(i){return this.each(function(){var t=g(this),e=t.data(ht),n=l({},dt,t.data(),"object"==typeof i&&i?i:{});if(!e&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),e||(e=new a(this,n),t.data(ht,e)),"string"==typeof i){if("undefined"==typeof e[i])throw new TypeError('No method n
13218amed "'+i+'"');e[i]()}})},s(a,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return dt}}]),a}();g(document).on(_t.CLICK_DATA_API,St,function(t){"A"===t.currentTarget.tagName&&t.preventDefault();var n=g(this),e=_.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(e));g(i).each(function(){var t=g(this),e=t.data(ht)?"toggle":n.data();bt._jQueryInterface.call(t,e)})}),g.fn[ct]=bt._jQueryInterface,g.fn[ct].Constructor=bt,g.fn[ct].noConflict=function(){return g.fn[ct]=ft,bt._jQueryInterface};var It="dropdown",Dt="bs.dropdown",wt="."+Dt,At=".data-api",Nt=g.fn[It],Ot=new RegExp("38|40|27"),kt={HIDE:"hide"+wt,HIDDEN:"hidden"+wt,SHOW:"show"+wt,SHOWN:"shown"+wt,CLICK:"click"+wt,CLICK_DATA_API:"click"+wt+At,KEYDOWN_DATA_API:"keydown"+wt+At,KEYUP_DATA_API:"keyup"+wt+At},Pt="disabled",Lt="show",jt="dropup",Ht="dropright",Rt="dropleft",xt="dropdown-menu-right",Ft="position-static",Ut='[data-toggle="dropdown"]',Wt=".dropdown form",qt=".dropdown-menu",Mt=".navbar-nav",Kt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Qt="top-start",Bt="top-end",Vt="bottom-start",Yt="bottom-end",zt="right-start",Xt="left-start",$t={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Gt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Jt=function(){function c(t,e){this._element=t,this._popper=null,this._config=this._getConfig(e),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var t=c.prototype;return t.toggle=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)){var t=c._getParentFromElement(this._element),e=g(this._menu).hasClass(Lt);if(c._clearMenus(),!e){var n={relatedTarget:this._element},i=g.Event(kt.SHOW,n);if(g(t).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof u)throw new TypeError("Bootstrap's dropdowns require Popper.js (https://popper.js.org/)");var o=this._element;"parent"===this._config.reference?o=t:_.isElement(this._config.reference)&&(o=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(o=this._config.reference[0])),"scrollParent"!==this._config.boundary&&g(t).addClass(Ft),this._popper=new u(o,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===g(t).closest(Mt).length&&g(document.body).children().on("mouseover",null,g.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),g(this._menu).toggleClass(Lt),g(t).toggleClass(Lt).trigger(g.Event(kt.SHOWN,n))}}}},t.show=function(){if(!(this._element.disabled||g(this._element).hasClass(Pt)||g(this._menu).hasClass(Lt))){var t={relatedTarget:this._element},e=g.Event(kt.SHOW,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.SHOWN,t)))}},t.hide=function(){if(!this._element.disabled&&!g(this._element).hasClass(Pt)&&g(this._menu).hasClass(Lt)){var t={relatedTarget:this._element},e=g.Event(kt.HIDE,t),n=c._getParentFromElement(this._element);g(n).trigger(e),e.isDefaultPrevented()||(g(this._menu).toggleClass(Lt),g(n).toggleClass(Lt).trigger(g.Event(kt.HIDDEN,t)))}},t.dispose=function(){g.removeData(this._element,Dt),g(this._element).off(wt),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},t.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},t._addEventListeners=function(){var e=this;g(this._element).on(kt.CLICK,function(t){t.preventDefault(),t.stopPropagation(),e.toggle()})},t._getConfig=function(t){return t=l({},this.constructor.Default,g(this._element).data(),t),_.typeCheckConfig(It,t,this.constructor.DefaultType),t},t._getMenuElement=function(){if(!this._menu){var t=c._getParentFromElement(this._element);t&&(this._menu=t.querySelector(qt))}return this._menu},t._getPlacement=function(){var t=g(this._element.parentNode),e=Vt;return t.hasClass(jt)?(e=Qt,g(this._menu).hasClass(xt)&&(e=Bt)):t.hasClass(Ht)?e=zt:t.hasClass(Rt)?e=Xt:g(this._menu).hasClass(xt)&&(e=Yt),e},t._detectNavbar=function(){return 0<g(this._element).closest(".
13218navbar").length},t._getOffset=function(){var e=this,t={};return"function"==typeof this._config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e._config.offset(t.offsets,e._element)||{}),t}:t.offset=this._config.offset,t},t._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),t},c._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(Dt);if(t||(t=new c(this,"object"==typeof e?e:null),g(this).data(Dt,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},c._clearMenus=function(t){if(!t||3!==t.which&&("keyup"!==t.type||9===t.which))for(var e=[].slice.call(document.querySelectorAll(Ut)),n=0,i=e.length;n<i;n++){var o=c._getParentFromElement(e[n]),r=g(e[n]).data(Dt),s={relatedTarget:e[n]};if(t&&"click"===t.type&&(s.clickEvent=t),r){var a=r._menu;if(g(o).hasClass(Lt)&&!(t&&("click"===t.type&&/input|textarea/i.test(t.target.tagName)||"keyup"===t.type&&9===t.which)&&g.contains(o,t.target))){var l=g.Event(kt.HIDE,s);g(o).trigger(l),l.isDefaultPrevented()||("ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),e[n].setAttribute("aria-expanded","false"),g(a).removeClass(Lt),g(o).removeClass(Lt).trigger(g.Event(kt.HIDDEN,s)))}}}},c._getParentFromElement=function(t){var e,n=_.getSelectorFromElement(t);return n&&(e=document.querySelector(n)),e||t.parentNode},c._dataApiKeydownHandler=function(t){if((/input|textarea/i.test(t.target.tagName)?!(32===t.which||27!==t.which&&(40!==t.which&&38!==t.which||g(t.target).closest(qt).length)):Ot.test(t.which))&&(t.preventDefault(),t.stopPropagation(),!this.disabled&&!g(this).hasClass(Pt))){var e=c._getParentFromElement(this),n=g(e).hasClass(Lt);if(n&&(!n||27!==t.which&&32!==t.which)){var i=[].slice.call(e.querySelectorAll(Kt));if(0!==i.length){var o=i.indexOf(t.target);38===t.which&&0<o&&o--,40===t.which&&o<i.length-1&&o++,o<0&&(o=0),i[o].focus()}}else{if(27===t.which){var r=e.querySelector(Ut);g(r).trigger("focus")}g(this).trigger("click")}}},s(c,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return $t}},{key:"DefaultType",get:function(){return Gt}}]),c}();g(document).on(kt.KEYDOWN_DATA_API,Ut,Jt._dataApiKeydownHandler).on(kt.KEYDOWN_DATA_API,qt,Jt._dataApiKeydownHandler).on(kt.CLICK_DATA_API+" "+kt.KEYUP_DATA_API,Jt._clearMenus).on(kt.CLICK_DATA_API,Ut,function(t){t.preventDefault(),t.stopPropagation(),Jt._jQueryInterface.call(g(this),"toggle")}).on(kt.CLICK_DATA_API,Wt,function(t){t.stopPropagation()}),g.fn[It]=Jt._jQueryInterface,g.fn[It].Constructor=Jt,g.fn[It].noConflict=function(){return g.fn[It]=Nt,Jt._jQueryInterface};var Zt="modal",te="bs.modal",ee="."+te,ne=g.fn[Zt],ie={backdrop:!0,keyboard:!0,focus:!0,show:!0},oe={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},re={HIDE:"hide"+ee,HIDDEN:"hidden"+ee,SHOW:"show"+ee,SHOWN:"shown"+ee,FOCUSIN:"focusin"+ee,RESIZE:"resize"+ee,CLICK_DISMISS:"click.dismiss"+ee,KEYDOWN_DISMISS:"keydown.dismiss"+ee,MOUSEUP_DISMISS:"mouseup.dismiss"+ee,MOUSEDOWN_DISMISS:"mousedown.dismiss"+ee,CLICK_DATA_API:"click"+ee+".data-api"},se="modal-dialog-scrollable",ae="modal-scrollbar-measure",le="modal-backdrop",ce="modal-open",he="fade",ue="show",fe=".modal-dialog",de=".modal-body",ge='[data-toggle="modal"]',_e='[data-dismiss="modal"]',me=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",pe=".sticky-top",ve=function(){function o(t,e){this._config=this._getConfig(e),this._element=t,this._dialog=t.querySelector(fe),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollbarWidth=0}var t=o.prototype;return t.toggle=function(t){return this._isShown?this.hide():this.show(t)},t.show=function(t){var e=this;if(!this._isShown&&!this._isTransitioning){g(this._element).hasClass(he)&&(this._isTransitioning=!0);var n=g.Event(re.SHOW,{relatedTarget:t});g(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),g(this._element).on(re.CLICK_DISMISS,_e,function(t){return e.hide(t)}),g(this._dialog).on(re.MOUSEDOWN_DISMISS,function(){g(e._element).one(re.MOUSEUP_DISMISS,function(t){g(t.target).is(e._element)&&(e._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return e._showElement(t)}))}},t.hide=function(t){var e=this;if(t&&t.preventDefault(),this._isShown&&!this._isTransitioning){var n=g.Event(re.HIDE);if(g(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=g(this._element).hasClass(he);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),g(document).off(re.FOCUSIN),g(this._element).removeClass(ue),g(this._element).off(re.CLICK_DISMISS),g(this._dialog).off(re.MOUSEDOWN_DISMISS),i){var o=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,function(t){return e._hideModal(t)}).emulateTransitionEnd(o)}else this._hideModal()}}},t.dispose=function(){[window,this._element,this._dialog].forEach(function(t){return g(t).off(ee)}),g(document).off(re.FOCUSIN),g.removeData(this._element,te),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._isTransitioning=null,this._scrollbarWidth=null},t.handleUpdate=function(){this._adjustDialog()},t._getConfig=function(t){return t=l({},ie,t),_.typeCheckConfig(Zt,t,oe),t},t._showElement=function(t){var e=this,n=g(this._element).hasClass(he);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),g(this._dialog).hasClass(se)?this._dialog.querySelector(de).scrollTop=0:this._element.scrollTop=0,n&&_.reflow(this._element),g(this._element).addClass(ue),this._config.focus&&this._enforceFocus();
13218var i=g.Event(re.SHOWN,{relatedTarget:t}),o=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,g(e._element).trigger(i)};if(n){var r=_.getTransitionDurationFromElement(this._dialog);g(this._dialog).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()},t._enforceFocus=function(){var e=this;g(document).off(re.FOCUSIN).on(re.FOCUSIN,function(t){document!==t.target&&e._element!==t.target&&0===g(e._element).has(t.target).length&&e._element.focus()})},t._setEscapeEvent=function(){var e=this;this._isShown&&this._config.keyboard?g(this._element).on(re.KEYDOWN_DISMISS,function(t){27===t.which&&(t.preventDefault(),e.hide())}):this._isShown||g(this._element).off(re.KEYDOWN_DISMISS)},t._setResizeEvent=function(){var e=this;this._isShown?g(window).on(re.RESIZE,function(t){return e.handleUpdate(t)}):g(window).off(re.RESIZE)},t._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._isTransitioning=!1,this._showBackdrop(function(){g(document.body).removeClass(ce),t._resetAdjustments(),t._resetScrollbar(),g(t._element).trigger(re.HIDDEN)})},t._removeBackdrop=function(){this._backdrop&&(g(this._backdrop).remove(),this._backdrop=null)},t._showBackdrop=function(t){var e=this,n=g(this._element).hasClass(he)?he:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=le,n&&this._backdrop.classList.add(n),g(this._backdrop).appendTo(document.body),g(this._element).on(re.CLICK_DISMISS,function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._element.focus():e.hide())}),n&&_.reflow(this._backdrop),g(this._backdrop).addClass(ue),!t)return;if(!n)return void t();var i=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){g(this._backdrop).removeClass(ue);var o=function(){e._removeBackdrop(),t&&t()};if(g(this._element).hasClass(he)){var r=_.getTransitionDurationFromElement(this._backdrop);g(this._backdrop).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o()}else t&&t()},t._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},t._setScrollbar=function(){var o=this;if(this._isBodyOverflowing){var t=[].slice.call(document.querySelectorAll(me)),e=[].slice.call(document.querySelectorAll(pe));g(t).each(function(t,e){var n=e.style.paddingRight,i=g(e).css("padding-right");g(e).data("padding-right",n).css("padding-right",parseFloat(i)+o._scrollbarWidth+"px")}),g(e).each(function(t,e){var n=e.style.marginRight,i=g(e).css("margin-right");g(e).data("margin-right",n).css("margin-right",parseFloat(i)-o._scrollbarWidth+"px")});var n=document.body.style.paddingRight,i=g(document.body).css("padding-right");g(document.body).data("padding-right",n).css("padding-right",parseFloat(i)+this._scrollbarWidth+"px")}g(document.body).addClass(ce)},t._resetScrollbar=function(){var t=[].slice.call(document.querySelectorAll(me));g(t).each(function(t,e){var n=g(e).data("padding-right");g(e).removeData("padding-right"),e.style.paddingRight=n||""});var e=[].slice.call(document.querySelectorAll(""+pe));g(e).each(function(t,e){var n=g(e).data("margin-right");"undefined"!=typeof n&&g(e).css("margin-right",n).removeData("margin-right")});var n=g(document.body).data("padding-right");g(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},t._getScrollbarWidth=function(){var t=document.createElement("div");t.className=ae,document.body.appendChild(t);var e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e},o._jQueryInterface=function(n,i){return this.each(function(){var t=g(this).data(te),e=l({},ie,g(this).data(),"object"==typeof n&&n?n:{});if(t||(t=new o(this,e),g(this).data(te,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n](i)}else e.show&&t.show(i)})},s(o,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return ie}}]),o}();g(document).on(re.CLICK_DATA_API,ge,function(t){var e,n=this,i=_.getSelectorFromElement(this);i&&(e=document.querySelector(i));var o=g(e).data(te)?"toggle":l({},g(e).data(),g(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||t.preventDefault();var r=g(e).one(re.SHOW,function(t){t.isDefaultPrevented()||r.one(re.HIDDEN,function(){g(n).is(":visible")&&n.focus()})});ve._jQueryInterface.call(g(e),o,this)}),g.fn[Zt]=ve._jQueryInterface,g.fn[Zt].Constructor=ve,g.fn[Zt].noConflict=function(){return g.fn[Zt]=ne,ve._jQueryInterface};var ye=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],Ee={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Ce=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,Te=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function Se(t,s,e){if(0===t.length)return t;if(e&&"function"==typeof e)return e(t);for(var n=(new window.DOMParser).parseFromString(t,"text/html"),a=Object.keys(s),l=[].slice.call(n.body.querySelectorAll("*")),i=function(t,e){var n=l[t],i=n.nodeName.toLowerCase();if(-1===a.indexOf(n.nodeName.toLowerCase()))return n.parentNode.removeChild(n),"continue";var o=[].slice.call(n.attributes),r=[].concat(s["*"]||[],s[i]||[]);o.forEach(function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===ye.indexOf(n)||Boolean(t.nodeValue.match(Ce)||t.nodeValue.match(Te));for(var i=e.filter(function(t){return t instanceof RegExp}),o=0,r=i.length;o<r;o++)if(n.match(i[o]))return!0;return!1})(t,r)||n.removeAttribute(t.nodeName)})},o=0,r=l.length;o<r;o++)i(o);return n.body.innerHTML}var be="tooltip",Ie="bs.tooltip",De="."+Ie,we=g.fn[be],Ae="bs-tooltip",Ne=new RegExp("(^|\\s)"+Ae+"\\S+","g"),Oe=["sanitize","whiteList","sanitizeFn"],ke={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object"},Pe={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},Le={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We}
13218,preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method n
13218amed "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0<e.length&&t.removeClass(e.join(""))},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ye),e="object"==typeof n?n:null;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Je}},{key:"NAME",get:function(){return Ve}},{key:"DATA_KEY",get:function(){return Ye}},{key:"Event",get:function(){return rn}},{key:"EVENT_KEY",get:function(){return ze}},{key:"DefaultType",get:function(){return Ze}}]),i}(Be);g.fn[Ve]=sn._jQueryInterface,g.fn[Ve].Constructor=sn,g.fn[Ve].noConflict=function(){return g.fn[Ve]=Xe,sn._jQueryInterface};var an="scrollspy",ln="bs.scrollspy",cn="."+ln,hn=g.fn[an],un={offset:10,method:"auto",target:""},fn={offset:"number",method:"string",target:"(string|element)"},dn={ACTIVATE:"activate"+cn,SCROLL:"scroll"+cn,LOAD_DATA_API:"load"+cn+".data-api"},gn="dropdown-item",_n="active",mn='[data-spy="scroll"]',pn=".nav, .list-group",vn=".nav-link",yn=".nav-item",En=".list-group-item",Cn=".dropdown",Tn=".dropdown-item",Sn=".dropdown-toggle",bn="offset",In="position",Dn=function(){function n(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" "+vn+","+this._config.target+" "+En+","+this._config.target+" "+Tn,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,g(this._scrollElement).on(dn.SCROLL,function(t){return n._process(t)}),this.refresh(),this._process()}var t=n.prototype;return t.refresh=function(){var e=this,t=this._scrollElement===this._scrollElement.window?bn:In,o="auto"===this._config.method?t:this._config.method,r=o===In?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map(function(t){var e,n=_.getSelectorFromElement(t);if(n&&(e=document.querySelector(n)),e){var i=e.getBoundingClientRect();if(i.width||i.height)return[g(e)[o]().top+r,n]}return null}).filter(function(t){return t}).sort(function(t,e){return t[0]-e[0]}
13218).forEach(function(t){e._offsets.push(t[0]),e._targets.push(t[1])})},t.dispose=function(){g.removeData(this._element,ln),g(this._scrollElement).off(cn),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},t._getConfig=function(t){if("string"!=typeof(t=l({},un,"object"==typeof t&&t?t:{})).target){var e=g(t.target).attr("id");e||(e=_.getUID(an),g(t.target).attr("id",e)),t.target="#"+e}return _.typeCheckConfig(an,t,fn),t},t._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},t._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},t._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},t._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),n<=t){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;){this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t<this._offsets[o+1])&&this._activate(this._targets[o])}}},t._activate=function(e){this._activeTarget=e,this._clear();var t=this._selector.split(",").map(function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'}),n=g([].slice.call(document.querySelectorAll(t.join(","))));n.hasClass(gn)?(n.closest(Cn).find(Sn).addClass(_n),n.addClass(_n)):(n.addClass(_n),n.parents(pn).prev(vn+", "+En).addClass(_n),n.parents(pn).prev(yn).children(vn).addClass(_n)),g(this._scrollElement).trigger(dn.ACTIVATE,{relatedTarget:e})},t._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter(function(t){return t.classList.contains(_n)}).forEach(function(t){return t.classList.remove(_n)})},n._jQueryInterface=function(e){return this.each(function(){var t=g(this).data(ln);if(t||(t=new n(this,"object"==typeof e&&e),g(this).data(ln,t)),"string"==typeof e){if("undefined"==typeof t[e])throw new TypeError('No method named "'+e+'"');t[e]()}})},s(n,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return un}}]),n}();g(window).on(dn.LOAD_DATA_API,function(){for(var t=[].slice.call(document.querySelectorAll(mn)),e=t.length;e--;){var n=g(t[e]);Dn._jQueryInterface.call(n,n.data())}}),g.fn[an]=Dn._jQueryInterface,g.fn[an].Constructor=Dn,g.fn[an].noConflict=function(){return g.fn[an]=hn,Dn._jQueryInterface};var wn="bs.tab",An="."+wn,Nn=g.fn.tab,On={HIDE:"hide"+An,HIDDEN:"hidden"+An,SHOW:"show"+An,SHOWN:"shown"+An,CLICK_DATA_API:"click"+An+".data-api"},kn="dropdown-menu",Pn="active",Ln="disabled",jn="fade",Hn="show",Rn=".dropdown",xn=".nav, .list-group",Fn=".active",Un="> li > .active",Wn='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',qn=".dropdown-toggle",Mn="> .dropdown-menu .active",Kn=function(){function i(t){this._element=t}var t=i.prototype;return t.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&g(this._element).hasClass(Pn)||g(this._element).hasClass(Ln))){var t,i,e=g(this._element).closest(xn)[0],o=_.getSelectorFromElement(this._element);if(e){var r="UL"===e.nodeName||"OL"===e.nodeName?Un:Fn;i=(i=g.makeArray(g(e).find(r)))[i.length-1]}var s=g.Event(On.HIDE,{relatedTarget:this._element}),a=g.Event(On.SHOW,{relatedTarget:i});if(i&&g(i).trigger(s),g(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(t=document.querySelector(o)),this._activate(this._element,e);var l=function(){var t=g.Event(On.HIDDEN,{relatedTarget:n._element}),e=g.Event(On.SHOWN,{relatedTarget:i});g(i).trigger(t),g(n._element).trigger(e)};t?this._activate(t,t.parentNode,l):l()}}},t.dispose=function(){g.removeData(this._element,wn),this._element=null},t._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?g(e).children(Fn):g(e).find(Un))[0],r=n&&o&&g(o).hasClass(jn),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=_.getTransitionDurationFromElement(o);g(o).removeClass(Hn).one(_.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},t._transitionComplete=function(t,e,n){if(e){g(e).removeClass(Pn);var i=g(e.parentNode).find(Mn)[0];i&&g(i).removeClass(Pn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}if(g(t).addClass(Pn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),_.reflow(t),t.classList.contains(jn)&&t.classList.add(Hn),t.parentNode&&g(t.parentNode).hasClass(kn)){var o=g(t).closest(Rn)[0];if(o){var r=[].slice.call(o.querySelectorAll(qn));g(r).addClass(Pn)}t.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(wn);if(e||(e=new i(this),t.data(wn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method n
13218amed "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}}]),i}();g(document).on(On.CLICK_DATA_API,Wn,function(t){t.preventDefault(),Kn._jQueryInterface.call(g(this),"show")}),g.fn.tab=Kn._jQueryInterface,g.fn.tab.Constructor=Kn,g.fn.tab.noConflict=function(){return g.fn.tab=Nn,Kn._jQueryInterface};var Qn="toast",Bn="bs.toast",Vn="."+Bn,Yn=g.fn[Qn],zn={CLICK_DISMISS:"click.dismiss"+Vn,HIDE:"hide"+Vn,HIDDEN:"hidden"+Vn,SHOW:"show"+Vn,SHOWN:"shown"+Vn},Xn="fade",$n="hide",Gn="show",Jn="showing",Zn={animation:"boolean",autohide:"boolean",delay:"number"},ti={animation:!0,autohide:!0,delay:500},ei='[data-dismiss="toast"]',ni=function(){function i(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var t=i.prototype;return t.show=function(){var t=this;g(this._element).trigger(zn.SHOW),this._config.animation&&this._element.classList.add(Xn);var e=function(){t._element.classList.remove(Jn),t._element.classList.add(Gn),g(t._element).trigger(zn.SHOWN),t._config.autohide&&t.hide()};if(this._element.classList.remove($n),this._element.classList.add(Jn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},t.hide=function(t){var e=this;this._element.classList.contains(Gn)&&(g(this._element).trigger(zn.HIDE),t?this._close():this._timeout=setTimeout(function(){e._close()},this._config.delay))},t.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(Gn)&&this._element.classList.remove(Gn),g(this._element).off(zn.CLICK_DISMISS),g.removeData(this._element,Bn),this._element=null,this._config=null},t._getConfig=function(t){return t=l({},ti,g(this._element).data(),"object"==typeof t&&t?t:{}),_.typeCheckConfig(Qn,t,this.constructor.DefaultType),t},t._setListeners=function(){var t=this;g(this._element).on(zn.CLICK_DISMISS,ei,function(){return t.hide(!0)})},t._close=function(){var t=this,e=function(){t._element.classList.add($n),g(t._element).trigger(zn.HIDDEN)};if(this._element.classList.remove(Gn),this._config.animation){var n=_.getTransitionDurationFromElement(this._element);g(this._element).one(_.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var t=g(this),e=t.data(Bn);if(e||(e=new i(this,"object"==typeof n&&n),t.data(Bn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"DefaultType",get:function(){return Zn}},{key:"Default",get:function(){return ti}}]),i}();g.fn[Qn]=ni._jQueryInterface,g.fn[Qn].Constructor=ni,g.fn[Qn].noConflict=function(){return g.fn[Qn]=Yn,ni._jQueryInterface},function(){if("undefined"==typeof g)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=g.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(),t.Util=_,t.Alert=p,t.Button=P,t.Carousel=lt,t.Collapse=bt,t.Dropdown=Jt,t.Modal=ve,t.Popover=sn,t.Scrollspy=Dn,t.Tab=Kn,t.Toast=ni,t.Tooltip=Be,Object.defineProperty(t,"__esModule",{value:!0})}); 13219//# sourceMappingURL=bootstrap.min.js.map 13220/*! 13221 * JavaScript Cookie v2.2.0 13222 * https://github.com/js-cookie/js-cookie 13223 * 13224 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 13225 * Released under the MIT license 13226 */ 13227;(function (factory) { 13228 var registeredInModuleLoader = false;
13229 if (typeof define === 'function' && define.amd) { 13230 define(factory); 13231 registeredInModuleLoader = true; 13232 } 13233 if (typeof exports === 'object') { 13234 module.exports = factory(); 13235 registeredInModuleLoader = true; 13236 } 13237 if (!registeredInModuleLoader) { 13238 var OldCookies = window.Cookies; 13239 var api = window.Cookies = factory(); 13240 api.noConflict = function () { 13241 window.Cookies = OldCookies; 13242 return api; 13243 }; 13244 } 13245}(function () { 13246 function extend () { 13247 var i = 0; 13248 var result = {}; 13249 for (; i < arguments.length; i++) { 13250 var attributes = arguments[ i ]; 13251 for (var key in attributes) { 13252 result[key] = attributes[key]; 13253 } 13254 } 13255 return result; 13256 } 13257 13258 function init (converter) { 13259 function api (key, value, attributes) { 13260 var result; 13261 if (typeof document === 'undefined') { 13262 return; 13263 } 13264 13265 // Write 13266 13267 if (arguments.length > 1) { 13268 attributes = extend({ 13269 path: '/' 13270 }, api.defaults, attributes); 13271 13272 if (typeof attributes.expires === 'number') { 13273 var expires = new Date(); 13274 expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 13275 attributes.expires = expires; 13276 } 13277 13278 // We're using "expires" because "max-age" is not supported by IE 13279 attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; 13280 13281 try { 13282 result = JSON.stringify(value); 13283 if (/^[\{\[]/.test(result)) { 13284 value = result; 13285 } 13286 } catch (e) {} 13287 13288 if (!converter.write) { 13289 value = encodeURIComponent(String(value)) 13290 .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 13291 } else { 13292 value = converter.write(value, key); 13293 } 13294 13295 key = encodeURIComponent(String(key)); 13296 key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 13297 key = key.replace(/[\(\)]/g, escape); 13298 13299 var stringifiedAttributes = ''; 13300 13301 for (var attributeName in attributes) { 13302 if (!attributes[attributeName]) { 13303 continue; 13304 } 13305 stringifiedAttributes += '; ' + attributeName; 13306 if (attributes[attributeName] === true) { 13307 continue; 13308 } 13309 stringifiedAttributes += '=' + attributes[attributeName]; 13310 } 13311 return (document.cookie = key + '=' + value + stringifiedAttributes); 13312 } 13313 13314 // Read 13315 13316 if (!key) { 13317 result = {}; 13318 } 13319 13320 // To prevent the for loop in the first place assign an empty array 13321 // in case there are no cookies at all. Also prevents odd result when 13322 // calling "get()" 13323 var cookies = document.cookie ? document.cookie.split('; ') : []; 13324 var rdecode = /(%[0-9A-Z]{2})+/g; 13325 var i = 0; 13326 13327 for (; i < cookies.length; i++) { 13328 var parts = cookies[i].split('='); 13329 var cookie = parts.slice(1).join('='); 13330 13331 if (!this.json && cookie.charAt(0) === '"') { 13332 cookie = cookie.slice(1, -1); 13333 } 13334 13335 try { 13336 var name = parts[0].replace(rdecode, decodeURIComponent); 13337 cookie = converter.read ? 13338 converter.read(cookie, name) : converter(cookie, name) || 13339 cookie.replace(rdecode, decodeURIComponent); 13340 13341 if (this.json) { 13342 try { 13343 cookie = JSON.parse(cookie); 13344 } catch (e) {} 13345 } 13346 13347 if (key === name) { 13348 result = cookie; 13349 break; 13350 } 13351 13352 if (!key) { 13353 result[name] = cookie; 13354 } 13355 } catch (e) {} 13356 } 13357 13358 return result; 13359 } 13360 13361 api.set = api; 13362 api.get = function (key) { 13363 return api.call(api, key); 13364 }; 13365 api.getJSON = function () { 13366 return api.apply({ 13367 json: true 13368 }, [].slice.call(arguments)); 13369 }; 13370 api.defaults = {}; 13371 13372 api.remove = function (key, attributes) { 13373 api(key, '', extend(attributes, { 13374 expires: -1 13375 })); 13376 }; 13377 13378 api.withConverter = init; 13379 13380 return api; 13381 } 13382 13383 return init(function () {}); 13384})); 13385
vendor: 53,324 bytes, line 13386
13386!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Tt(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function v(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function p(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function k(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function S(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function D(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=S(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&D(e[s])!==D(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function b(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function x(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function C(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function H(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function R(e){var t,n,s={};for(n in e)m(e,n)&&(t=H(n))&&(s[t]=e[n]);return s}var U={};function F(e,t){U[e]=t}function L(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return L(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=b(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=b(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(he(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function he(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var de={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),h(n)&&(s=function(e,t){t[n]=D(e)}),t=0;t<e.length;t++)de[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,ve=4,pe=5,we=6,Me=7,ke=8;function Se(e){return De(e)?366:365}function De(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),C("year","y"),F("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):D(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return D(e)+(68<D(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(xe(this,t,e),c.updateOffset(this,n),this):be(this,t)}}function be(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&De(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?De(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),C("month","M"),F("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=D(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var He="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Re(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=D(t);else if(!h(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Ue(e){return null!=e?(Re(this,e),c.updateOffset(this,!0),this):be(this,"Month")}var Fe=ae;var Le=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=he(s[t]),i[t]=he(i[t]);for(t=0;t<24;t++)r[t]=he(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t;if(e<100&&0<=e){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return a=o<=0?Se(r=e-1)+o:o>Se(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=at(e[r]).split("-")).length,n=(n=at(e[r+1]))?n.split("-"):null;0<t;){if(s=ot(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[ve]||0!==n[pe]||0!==n[we])?ge:n[ve]<0||59<n[ve]?ve:n[pe]<0||59<n[pe]?pe:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=ke),g(e).overflow=t),e}function ct(e,t,n){return null!=e?e:null!=t?t:n}function ft(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ct(t.GG,e._a[me],Ie(bt(),1,4).year),s=ct(t.W,1),((i=ct(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(bt(),r,a);n=ct(t.gg,e._a[me],l.year),s=ct(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[1])){i=gt[t][0],s=!1!==gt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=vt.length;t<n;t++)if(vt[t][1].exec(u[3])){r=(u[2]||" ")+vt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!yt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Yt(e)}else e._isValid=!1}var Mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function kt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),He.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=Mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=kt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function Yt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,h=l.length,d=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),d+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(de,a)&&de[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=h-d,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ft(e),dt(e)}else Dt(e);else wt(e)}function Ot(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||ht(e._l),null===r||void 0===a&&""===r?p({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),k(r)?new M(dt(r)):(d(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Yt(t),v(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?Yt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):d(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(wt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ft(t)):u(n)?function(e){if(!e._d){var t=R(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ft(e)}}(t):h(n)?t._d=new Date(n):c.createFromInputFallback(t),v(e)||(e._d=null),e))}function Tt(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Ot(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function bt(e,t,n,s){return Tt(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:p()}),Pt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:p()});function Wt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return bt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Ct=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=R(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||t.isoWeek||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,h=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Ct,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Ct.length;++s)if(e[Ct[s]]){if(n)return!1;parseFloat(e[Ct[s]])!==D(e[Ct[s]])&&(n=!0)}return!0}(t),this._milliseconds=+h+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ht(),this._bubble()}function Rt(e){return e instanceof Ht}function Ut(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+L(~~(e/60),2)+n+L(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Nt(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Nt(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+D(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Gt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(k(e)||d(e)?e.valueOf():bt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):bt(e).local()}function Vt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Et(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var It=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,At=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function jt(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:h(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=It.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:D(a[ye])*n,h:D(a[ge])*n,m:D(a[ve])*n,s:D(a[pe])*n,ms:D(Ut(1e3*a[we]))*n}):(a=At.exec(e))?(n="-"===a[1]?-1:1,r={y:Zt(a[2],n),M:Zt(a[3],n),w:Zt(a[4],n),d:Zt(a[5],n),h:Zt(a[6],n),m:Zt(a[7],n),s:Zt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(bt(r.from),bt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function Zt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,jt(e="string"==typeof e?+e:e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ut(t._days),a=Ut(t._months);e.isValid()&&(s=null==s||s,a&&Re(e,be(e,"Month")+a*n),r&&xe(e,"Date",be(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}jt.fn=Ht.prototype,jt.invalid=function(){return jt(NaN)};var Jt=$t(1,"add"),Bt=$t(-1,"subtract");function Qt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Xt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ht(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Kt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function en(){return this._locale}var tn=126227808e5;function nn(e,t){return(e%t+t)%t}function sn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-tn:new Date(e,t,n).valueOf()}function rn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-tn:Date.UTC(e,t,n)}function an(e,t){I(0,[e,e.length],0,t)}function on(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),C("weekYear","gg"),C("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=D(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),C("quarter","Q"),F("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(D(e)-1)}),I("D",["DD",2],"Do","date"),C("date","D"),F("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=D(e.match(B)[0])});var un=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),C("dayOfYear","DDD"),F("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=D(e)}),I("m",["mm",2],0,"minute"),C("minute","m"),F("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],ve);var ln=Te("Minutes",!1);I("s",["ss",2],0,"second"),C("second","s"),F("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],pe);var hn,dn=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),C("millisecond","ms"),F("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),hn="SSSS";hn.length<=9;hn+="S")ue(hn,ne);function cn(e,t){t[we]=D(1e3*("0."+e))}for(hn="S";hn.length<=9;hn+="S")ce(hn,cn);var fn=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var mn=M.prototype;function _n(e){return e}mn.add=Jt,mn.calendar=function(e,t){var n=e||bt(),s=Gt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(b(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,bt(n)))},mn.clone=function(){return new M(this)},mn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=H(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:S(r)},mn.endOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-nn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-nn(t,1e3)-1;break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},mn.from=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.fromNow=function(e){return this.from(bt(),e)},mn.to=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.toNow=function(e){return this.to(bt(),e)},mn.get=function(e){return b(this[e=H(e)])?this[e]():this},mn.invalidAt=function(){return g(this).overflow},mn.isAfter=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},mn.isBefore=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},mn.isBetween=function(e,t,n,s){var i=k(e)?e:bt(e),r=k(t)?t:bt(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n))},mn.isSame=function(e,t){var n,s=k(e)?e:bt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},mn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},mn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},mn.isValid=function(){return v(this)},mn.lang=Kt,mn.locale=Xt,mn.localeData=en,mn.max=Pt,mn.min=xt,mn.parsingFlags=function(){return _({},g(this))},mn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:U[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=R(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(b(this[e=H(e)]))return this[e](t);return this},mn.startOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=nn(t,6e4);break;case"second":t=this._d.valueOf(),t-=nn(t,1e3);break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.subtract=Bt,mn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},mn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):b(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Oe,mn.isLeapYear=function(){return De(this.year())},mn.weekYear=function(e){return on.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(e){return on.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},mn.month=Ue,mn.daysInMonth=function(){return Pe(this.year(),this.month())},mn.week=mn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},mn.isoWeek=mn.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},mn.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},mn.isoWeeksInYear=function(){return Ae(this.year(),1,4)},mn.date=un,mn.day=mn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},mn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},mn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null==e)return this.day()||7;var t,n,s=(t=e,n=this.localeData(),"string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t);return this.day(this.day()%7?s:s-7)},mn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},mn.hour=mn.hours=nt,mn.minute=mn.minutes=ln,mn.second=mn.seconds=dn,mn.millisecond=mn.milliseconds=fn,mn.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Vt(this);if("string"==typeof e){if(null===(e=Nt(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Vt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,jt(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this},mn.utc=function(e){return this.utcOffset(0,e)},mn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Vt(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Nt(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?bt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var yn=P.prototype;function gn(e,t,n,s){var i=ht(),r=y().set(s,t);return i[n](r,e)}function vn(e,t,n){if(h(e)&&(t=e,e=void 0),e=e||"",null!=t)return gn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=gn(e,s,n,"month");return i}function pn(e,t,n,s){t=("boolean"==typeof e?h(t)&&(n=t,t=void 0):(t=e,e=!1,h(n=t)&&(n=t,t=void 0)),t||"");var i,r=ht(),a=e?r._week.dow:0;if(null!=n)return gn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=gn(t,(i+a)%7,s,"day");return o}yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return b(s)?s.call(t,n):s},yn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},yn.invalidDate=function(){return this._invalidDate},yn.ordinal=function(e){return this._ordinal.replace("%d",e)},yn.preparse=_n,yn.postformat=_n,yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return b(i)?i(e,t,n,s):i.replace(/%d/i,e)},yn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return b(n)?n(t):n.replace(/%s/i,t)},yn.set=function(e){var t,n;for(n in e)b(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},yn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},yn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},yn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},yn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},yn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},yn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},yn.firstDayOfYear=function(){return this._week.doy},yn.firstDayOfWeek=function(){return this._week.dow},yn.weekdays=function(e,t){var n=o(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?je(n,this._week.dow):e?n[e.day()]:n},yn.weekdaysMin=function(e){return!0===e?je(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},yn.weekdaysShort=function(e){return!0===e?je(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},yn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=qe),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Be),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},yn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ut("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===D(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ut),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",ht);var wn=Math.abs;function Mn(e,t,n,s){var i=jt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function kn(e){return e<0?Math.floor(e):Math.ceil(e)}function Sn(e){return 4800*e/146097}function Dn(e){return 146097*e/4800}function Yn(e){return function(){return this.as(e)}}var On=Yn("ms"),Tn=Yn("s"),bn=Yn("m"),xn=Yn("h"),Pn=Yn("d"),Wn=Yn("w"),Cn=Yn("M"),Hn=Yn("Q"),Rn=Yn("y");function Un(e){return function(){return this.isValid()?this._data[e]:NaN}}var Fn=Un("milliseconds"),Ln=Un("seconds"),Nn=Un("minutes"),Gn=Un("hours"),Vn=Un("days"),En=Un("months"),In=Un("years");var An=Math.round,jn={ss:44,s:45,m:45,h:22,d:26,M:11};var Zn=Math.abs;function zn(e){return(0<e)-(e<0)||+e}function $n(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Zn(this._milliseconds)/1e3,s=Zn(this._days),i=Zn(this._months);t=S((e=S(n/60))/60),n%=60,e%=60;var r=S(i/12),a=i%=12,o=s,u=t,l=e,h=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var c=d<0?"-":"",f=zn(this._months)!==zn(d)?"-":"",m=zn(this._days)!==zn(d)?"-":"",_=zn(this._milliseconds)!==zn(d)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||h?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(h?_+h+"S":"")}var qn=Ht.prototype;return qn.isValid=function(){return this._isValid},qn.abs=function(){var e=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),e.milliseconds=wn(e.milliseconds),e.seconds=wn(e.seconds),e.minutes=wn(e.minutes),e.hours=wn(e.hours),e.months=wn(e.months),e.years=wn(e.years),this},qn.add=function(e,t){return Mn(this,e,t,1)},qn.subtract=function(e,t){return Mn(this,e,t,-1)},qn.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=H(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+Sn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Dn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},qn.asMilliseconds=On,qn.asSeconds=Tn,qn.asMinutes=bn,qn.asHours=xn,qn.asDays=Pn,qn.asWeeks=Wn,qn.asMonths=Cn,qn.asQuarters=Hn,qn.asYears=Rn,qn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},qn._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*kn(Dn(o)+a),o=a=0),u.milliseconds=r%1e3,e=S(r/1e3),u.seconds=e%60,t=S(e/60),u.minutes=t%60,n=S(t/60),u.hours=n%24,o+=i=S(Sn(a+=S(n/24))),a-=kn(Dn(i)),s=S(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},qn.clone=function(){return jt(this)},qn.get=function(e){return e=H(e),this.isValid()?this[e+"s"]():NaN},qn.milliseconds=Fn,qn.seconds=Ln,qn.minutes=Nn,qn.hours=Gn,qn.days=Vn,qn.weeks=function(){return S(this.days()/7)},qn.months=En,qn.years=In,qn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,h,d,c=this.localeData(),f=(n=!e,s=c,i=jt(t=this).abs(),r=An(i.as("s")),a=An(i.as("m")),o=An(i.as("h")),u=An(i.as("d")),l=An(i.as("M")),h=An(i.as("y")),(d=r<=jn.ss&&["s",r]||r<jn.s&&["ss",r]||a<=1&&["m"]||a<jn.m&&["mm",a]||o<=1&&["h"]||o<jn.h&&["hh",o]||u<=1&&["d"]||u<jn.d&&["dd",u]||l<=1&&["M"]||l<jn.M&&["MM",l]||h<=1&&["y"]||["yy",h])[2]=n,d[3]=0<+t,d[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},qn.toISOString=$n,qn.toString=$n,qn.toJSON=$n,qn.locale=Xt,qn.localeData=en,qn.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$n),qn.lang=Kt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(D(e))}),c.version="2.24.0",e=bt,c.fn=mn,c.min=function(){return Wt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Wt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return bt(1e3*e)},c.months=function(e,t){return vn(e,t,"months")},c.isDate=d,c.locale=ut,c.invalid=p,c.duration=jt,c.isMoment=k,c.weekdays=function(e,t,n){return pn(e,t,n,"weekdays")},c.parseZone=function(){return bt.apply(null,arguments).parseZone()},c.localeData=ht,c.isDuration=Rt,c.monthsShort=function(e,t){return vn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return pn(e,t,n,"weekdaysMin")},c.defineLocale=lt,c.updateLocale=function(e,t){if(null!=t){var n,s,i=st;null!=(s=ot(e))&&(i=s._config),(n=new P(t=x(i,t))).parentLocale=it[e],it[e]=n,ut(e)}else null!=it[e]&&(null!=it[e].parentLocale?it[e]=it[e].parentLocale:null!=it[e]&&delete it[e]);return it[e]},c.locales=function(){return s(it)},c.weekdaysShort=function(e,t,n){return pn(e,t,n,"weekdaysShort")},c.normalizeUnits=H,c.relativeTimeRounding=function(e){return void 0===e?An:"function"==typeof e&&(An=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==jn[e]&&(void 0===t?jn[e]:(jn[e]=t,"s"===e&&(jn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=mn,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},c});
13386 13387/* 13388 Copyright (C) Federico Zivolo 2019 13389 Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). 13390 */(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b(require('popper.js')):'function'==typeof define&&define.amd?define(['popper.js'],b):a.Tooltip=b(a.Popper)})(this,function(a){'use strict';function b(a){return a&&'[object Function]'==={}.toString.call(a)}a=a&&a.hasOwnProperty('default')?a['default']:a;var c=function(a,b){if(!(a instanceof b))throw new TypeError('Cannot call a class as a function')},d=function(){function a(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,'value'in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),e=Object.assign||function(a){for(var b,c=1;c<arguments.length;c++)for(var d in b=arguments[c],b)Object.prototype.hasOwnProperty.call(b,d)&&(a[d]=b[d]);return a},f={container:!1,delay:0,html:!1,placement:'top',title:'',template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:'hover focus',offset:0,arrowSelector:'.tooltip-arrow, .tooltip__arrow',innerSelector:'.tooltip-inner, .tooltip__inner'},g=function(){function g(a,b){c(this,g),h.call(this),b=e({},f,b),a.jquery&&(a=a[0]),this.reference=a,this.options=b;var d='string'==typeof b.trigger?b.trigger.split(' ').filter(function(a){return-1!==['click','hover','focus'].indexOf(a)}):[];this._isOpen=!1,this._popperOptions={},this._setEventListeners(a,d,b)}return d(g,[{key:'_create',value:function(a,b,c,d){var e=window.document.createElement('div');e.innerHTML=b.trim();var f=e.childNodes[0];f.id='tooltip_'+Math.random().toString(36).substr(2,10),f.setAttribute('aria-hidden','false');var g=e.querySelector(this.options.innerSelector);return this._addTitleContent(a,c,d,g),f}},{key:'_addTitleContent',value:function(a,c,d,e){if(1===c.nodeType||11===c.nodeType)d&&e.appendChild(c);else if(b(c)){var f=c.call(a);d?e.innerHTML=f:e.textContent=f}else d?e.innerHTML=c:e.textContent=c}},{key:'_show',value:function(b,c){if(this._isOpen&&!this._isOpening)return this;if(this._isOpen=!0,this._tooltipNode)return this._tooltipNode.style.visibility='visible',this._tooltipNode.setAttribute('aria-hidden','false'),this.popperInstance.update(),this;var d=b.getAttribute('title')||c.title;if(!d)return this;var f=this._create(b,c.template,d,c.html);b.setAttribute('aria-describedby',f.id);var g=this._findContainer(c.container,b);return this._append(f,g),this._popperOptions=e({},c.popperOptions,{placement:c.placement}),this._popperOptions.modifiers=e({},this._popperOptions.modifiers,{arrow:e({},this._popperOptions.modifiers&&this._popperOptions.modifiers.arrow,{element:c.arrowSelector}),offset:e({},this._popperOptions.modifiers&&this._popperOptions.modifiers.offset,{offset:c.offset})}),c.boundariesElement&&(this._popperOptions.modifiers.preventOverflow={boundariesElement:c.boundariesElement}),this.popperInstance=new a(b,f,this._popperOptions),this._tooltipNode=f,this}},{key:'_hide',value:function(){return this._isOpen?(this._isOpen=!1,this._tooltipNode.style.visibility='hidden',this._tooltipNode.setAttribute('aria-hidden','true'),this):this}},{key:'_dispose',value:function(){var a=this;return this._events.forEach(function(b){var c=b.func,d=b.event;a.reference.removeEventListener(d,c)}),this._events=[],this._tooltipNode&&(this._hide(),this.popperInstance.destroy(),!this.popperInstance.options.removeOnDestroy&&(this._tooltipNode.parentNode.removeChild(this._tooltipNode),this._tooltipNode=null)),this}},{key:'_findContainer',value:function(a,b){return'string'==typeof a?a=window.document.querySelector(a):!1===a&&(a=b.parentNode),a}},{key:'_append',value:function(a,b){b.appendChild(a)}},{key:'_setEventListeners',value:function(a,b,c){var d=this,e=[],f=[];b.forEach(function(a){'hover'===a?(e.push('mouseenter'),f.push('mouseleave')):'focus'===a?(e.push('focus'),f.push('blur')):'click'===a?(e.push('click'),f.push('click')):void 0}),e.forEach(function(b){var e=function(b){!0===d._isOpening||(b.usedByTooltip=!0,d._scheduleShow(a,c.delay,c,b))};d._events.push({event:b,func:e}),a.addEventListener(b,e)}),f.forEach(function(b){var f=function(b){!0===b.usedByTooltip||d._scheduleHide(a,c.delay,c,b)};d._events.push({event:b,func:f}),a.addEventListener(b,f),'click'===b&&c.closeOnClickOutside&&document.addEventListener('mousedown',function(b){if(d._isOpening){var c=d.popperInstance.popper;a.contains(b.target)||c.contains(b.target)||f(b)}},!0)})}},{key:'_scheduleShow',value:function(a,b,c){var d=this;this._isOpening=!0;var e=b&&b.show||b||0;this._showTimeout=window.setTimeout(function(){return d._show(a,c)},e)}},{key:'_scheduleHide',value:function(a,b,c,d){var e=this;this._isOpening=!1;var f=b&&b.hide||b||0;window.clearTimeout(this._showTimeout),window.setTimeout(function(){if(!1!==e._isOpen&&document.body.contains(e._tooltipNode)){if('mouseleave'===d.type){var f=e._setTooltipNodeEvent(d,a,b,c);if(f)return}e._hide(a,c)}},f)}}
13390,{key:'_updateTitleContent',value:function(a){if('undefined'==typeof this._tooltipNode)return void('undefined'!=typeof this.options.title&&(this.options.title=a));var b=this._tooltipNode.querySelector(this.options.innerSelector);this._clearTitleContent(b,this.options.html,this.reference.getAttribute('title')||this.options.title),this._addTitleContent(this.reference,a,this.options.html,b),this.options.title=a,this.popperInstance.update()}},{key:'_clearTitleContent',value:function(a,b,c){1===c.nodeType||11===c.nodeType?b&&a.removeChild(c):b?a.innerHTML='':a.textContent=''}}]),g}(),h=function(){var a=this;this.show=function(){return a._show(a.reference,a.options)},this.hide=function(){return a._hide()},this.dispose=function(){return a._dispose()},this.toggle=function(){return a._isOpen?a.hide():a.show()},this.updateTitleContent=function(b){return a._updateTitleContent(b)},this._events=[],this._setTooltipNodeEvent=function(b,c,d,e){var f=b.relatedreference||b.toElement||b.relatedTarget;return!!a._tooltipNode.contains(f)&&(a._tooltipNode.addEventListener(b.type,function d(f){var g=f.relatedreference||f.toElement||f.relatedTarget;a._tooltipNode.removeEventListener(b.type,d),c.contains(g)||a._scheduleHide(c,e.delay,e,f)}),!0)}};return g}); 13391//# sourceMappingURL=tooltip.min.js.map 13392 13393/*! 13394 * perfect-scrollbar v1.4.0 13395 * (c) 2018 Hyunje Jun 13396 * @license MIT 13397 */ 13398(function (global, factory) { 13399 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 13400 typeof define === 'function' && define.amd ? define(factory) : 13401 (global.PerfectScrollbar = factory()); 13402}(this, (function () { 'use strict'; 13403 13404function get(element) { 13405 return getComputedStyle(element); 13406} 13407 13408function set(element, obj) { 13409 for (var key in obj) { 13410 var val = obj[key]; 13411 if (typeof val === 'number') { 13412 val = val + "px"; 13413 } 13414 element.style[key] = val; 13415 } 13416 return element; 13417} 13418 13419function div(className) { 13420 var div = document.createElement('div'); 13421 div.className = className; 13422 return div; 13423} 13424 13425var elMatches = 13426 typeof Element !== 'undefined' && 13427 (Element.prototype.matches || 13428 Element.prototype.webkitMatchesSelector || 13429 Element.prototype.mozMatchesSelector || 13430 Element.prototype.msMatchesSelector); 13431 13432function matches(element, query) { 13433 if (!elMatches) { 13434 throw new Error('No element matching method supported'); 13435 } 13436 13437 return elMatches.call(element, query); 13438} 13439 13440function remove(element) { 13441 if (element.remove) { 13442 element.remove(); 13443 } else { 13444 if (element.parentNode) { 13445 element.parentNode.removeChild(element); 13446 } 13447 } 13448} 13449 13450function queryChildren(element, selector) { 13451 return Array.prototype.filter.call(element.children, function (child) { return matches(child, selector); } 13452 ); 13453} 13454 13455var cls = { 13456 main: 'ps', 13457 element: { 13458 thumb: function (x) { return ("ps__thumb-" + x); }, 13459 rail: function (x) { return ("ps__rail-" + x); }, 13460 consuming: 'ps__child--consume', 13461 }, 13462 state: { 13463 focus: 'ps--focus', 13464 clicking: 'ps--clicking', 13465 active: function (x) { return ("ps--active-" + x); }, 13466 scrolling: function (x) { return ("ps--scrolling-" + x); }, 13467 }, 13468}; 13469 13470/* 13471 * Helper methods 13472 */ 13473var scrollingClassTimeout = { x: null, y: null }; 13474 13475function addScrollingClass(i, x) { 13476 var classList = i.element.classList; 13477 var className = cls.state.scrolling(x); 13478 13479 if (classList.contains(className)) { 13480 clearTimeout(scrollingClassTimeout[x]); 13481 } else { 13482 classList.add(className); 13483 } 13484} 13485 13486function removeScrollingClass(i, x) { 13487 scrollingClassTimeout[x] = setTimeout( 13488 function () { return i.isAlive && i.element.classList.remove(cls.state.scrolling(x)); }, 13489 i.settings.scrollingThreshold 13490 ); 13491} 13492 13493function setScrollingClassInstantly(i, x) { 13494 addScrollingClass(i, x); 13495 removeScrollingClass(i, x); 13496} 13497 13498var EventElement = function EventElement(element) { 13499 this.element = element; 13500 this.handlers = {}; 13501}; 13502 13503var prototypeAccessors = { isEmpty: { configurable: true } }; 13504 13505EventElement.prototype.bind = function bind (eventName, handler) { 13506 if (typeof this.handlers[eventName] === 'undefined') { 13507 this.handlers[eventName] = []; 13508 } 13509 this.handlers[eventName].push(handler); 13510 this.element.addEventListener(eventName, handler, false); 13511}; 13512 13513EventElement.prototype.unbind = function unbind (eventName, target) { 13514 var this$1 = this; 13515 13516 this.handlers[eventName] = this.handlers[eventName].filter(function (handler) { 13517 if (target && handler !== target) { 13518 return true; 13519 } 13520 this$1.element.removeEventListener(eventName, handler, false); 13521 return false;
vendor: 5,047 bytes, lines 13522-13727
13522 }); 13523}; 13524 13525EventElement.prototype.unbindAll = function unbindAll () { 13526 var this$1 = this; 13527 13528 for (var name in this$1.handlers) { 13529 this$1.unbind(name); 13530 } 13531}; 13532 13533prototypeAccessors.isEmpty.get = function () { 13534 var this$1 = this; 13535 13536 return Object.keys(this.handlers).every( 13537 function (key) { return this$1.handlers[key].length === 0; } 13538 ); 13539}; 13540 13541Object.defineProperties( EventElement.prototype, prototypeAccessors ); 13542 13543var EventManager = function EventManager() { 13544 this.eventElements = []; 13545}; 13546 13547EventManager.prototype.eventElement = function eventElement (element) { 13548 var ee = this.eventElements.filter(function (ee) { return ee.element === element; })[0]; 13549 if (!ee) { 13550 ee = new EventElement(element); 13551 this.eventElements.push(ee); 13552 } 13553 return ee; 13554}; 13555 13556EventManager.prototype.bind = function bind (element, eventName, handler) { 13557 this.eventElement(element).bind(eventName, handler); 13558}; 13559 13560EventManager.prototype.unbind = function unbind (element, eventName, handler) { 13561 var ee = this.eventElement(element); 13562 ee.unbind(eventName, handler); 13563 13564 if (ee.isEmpty) { 13565 // remove 13566 this.eventElements.splice(this.eventElements.indexOf(ee), 1); 13567 } 13568}; 13569 13570EventManager.prototype.unbindAll = function unbindAll () { 13571 this.eventElements.forEach(function (e) { return e.unbindAll(); }); 13572 this.eventElements = []; 13573}; 13574 13575EventManager.prototype.once = function once (element, eventName, handler) { 13576 var ee = this.eventElement(element); 13577 var onceHandler = function (evt) { 13578 ee.unbind(eventName, onceHandler); 13579 handler(evt); 13580 }; 13581 ee.bind(eventName, onceHandler); 13582}; 13583 13584function createEvent(name) { 13585 if (typeof window.CustomEvent === 'function') { 13586 return new CustomEvent(name); 13587 } else { 13588 var evt = document.createEvent('CustomEvent'); 13589 evt.initCustomEvent(name, false, false, undefined); 13590 return evt; 13591 } 13592} 13593 13594var processScrollDiff = function( 13595 i, 13596 axis, 13597 diff, 13598 useScrollingClass, 13599 forceFireReachEvent 13600) { 13601 if ( useScrollingClass === void 0 ) useScrollingClass = true; 13602 if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false; 13603 13604 var fields; 13605 if (axis === 'top') { 13606 fields = [ 13607 'contentHeight', 13608 'containerHeight', 13609 'scrollTop', 13610 'y', 13611 'up', 13612 'down' ]; 13613 } else if (axis === 'left') { 13614 fields = [ 13615 'contentWidth', 13616 'containerWidth', 13617 'scrollLeft', 13618 'x', 13619 'left', 13620 'right' ]; 13621 } else { 13622 throw new Error('A proper axis should be provided'); 13623 } 13624 13625 processScrollDiff$1(i, diff, fields, useScrollingClass, forceFireReachEvent); 13626}; 13627 13628function processScrollDiff$1( 13629 i, 13630 diff, 13631 ref, 13632 useScrollingClass, 13633 forceFireReachEvent 13634) { 13635 var contentHeight = ref[0]; 13636 var containerHeight = ref[1]; 13637 var scrollTop = ref[2]; 13638 var y = ref[3]; 13639 var up = ref[4]; 13640 var down = ref[5]; 13641 if ( useScrollingClass === void 0 ) useScrollingClass = true; 13642 if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false; 13643 13644 var element = i.element; 13645 13646 // reset reach 13647 i.reach[y] = null; 13648 13649 // 1 for subpixel rounding 13650 if (element[scrollTop] < 1) { 13651 i.reach[y] = 'start'; 13652 } 13653 13654 // 1 for subpixel rounding 13655 if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) { 13656 i.reach[y] = 'end'; 13657 } 13658 13659 if (diff) { 13660 element.dispatchEvent(createEvent(("ps-scroll-" + y))); 13661 13662 if (diff < 0) { 13663 element.dispatchEvent(createEvent(("ps-scroll-" + up))); 13664 } else if (diff > 0) { 13665 element.dispatchEvent(createEvent(("ps-scroll-" + down))); 13666 } 13667 13668 if (useScrollingClass) { 13669 setScrollingClassInstantly(i, y); 13670 } 13671 } 13672 13673 if (i.reach[y] && (diff || forceFireReachEvent)) { 13674 element.dispatchEvent(createEvent(("ps-" + y + "-reach-" + (i.reach[y])))); 13675 } 13676} 13677 13678function toInt(x) { 13679 return parseInt(x, 10) || 0; 13680} 13681 13682function isEditable(el) { 13683 return ( 13684 matches(el, 'input,[contenteditable]') || 13685 matches(el, 'select,[contenteditable]') || 13686 matches(el, 'textarea,[contenteditable]') || 13687 matches(el, 'button,[contenteditable]') 13688 ); 13689} 13690 13691function outerWidth(element) { 13692 var styles = get(element); 13693 return ( 13694 toInt(styles.width) + 13695 toInt(styles.paddingLeft) + 13696 toInt(styles.paddingRight) + 13697 toInt(styles.borderLeftWidth) + 13698 toInt(styles.borderRightWidth) 13699 ); 13700} 13701 13702var env = { 13703 isWebKit: 13704 typeof document !== 'undefined' && 13705 'WebkitAppearance' in document.documentElement.style, 13706 supportsTouch: 13707 typeof window !== 'undefined' && 13708 ('ontouchstart' in window || 13709 (window.DocumentTouch && document instanceof window.DocumentTouch)), 13710 supportsIePointer: 13711 typeof navigator !== 'undefined' && navigator.msMaxTouchPoints, 13712 isChrome: 13713 typeof navigator !== 'undefined' && 13714 /Chrome/i.test(navigator && navigator.userAgent), 13715}; 13716 13717var updateGeometry = function(i) { 13718 var element = i.element; 13719 var roundedScrollTop = Math.floor(element.scrollTop); 13720 13721 i.containerWidth = element.clientWidth; 13722 i.containerHeight = element.clientHeight; 13723 i.contentWidth = element.scrollWidth; 13724 i.contentHeight = element.scrollHeight; 13725 13726 if (!element.contains(i.scrollbarXRail)) { 13727 // clean up and append
vendor: 4,424 bytes, lines 13728-13879
13728 queryChildren(element, cls.element.rail('x')).forEach(function (el) { return remove(el); } 13729 ); 13730 element.appendChild(i.scrollbarXRail); 13731 } 13732 if (!element.contains(i.scrollbarYRail)) { 13733 // clean up and append 13734 queryChildren(element, cls.element.rail('y')).forEach(function (el) { return remove(el); } 13735 ); 13736 element.appendChild(i.scrollbarYRail); 13737 } 13738 13739 if ( 13740 !i.settings.suppressScrollX && 13741 i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth 13742 ) { 13743 i.scrollbarXActive = true; 13744 i.railXWidth = i.containerWidth - i.railXMarginWidth; 13745 i.railXRatio = i.containerWidth / i.railXWidth; 13746 i.scrollbarXWidth = getThumbSize( 13747 i, 13748 toInt(i.railXWidth * i.containerWidth / i.contentWidth) 13749 ); 13750 i.scrollbarXLeft = toInt( 13751 (i.negativeScrollAdjustment + element.scrollLeft) * 13752 (i.railXWidth - i.scrollbarXWidth) / 13753 (i.contentWidth - i.containerWidth) 13754 ); 13755 } else { 13756 i.scrollbarXActive = false; 13757 } 13758 13759 if ( 13760 !i.settings.suppressScrollY && 13761 i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight 13762 ) { 13763 i.scrollbarYActive = true; 13764 i.railYHeight = i.containerHeight - i.railYMarginHeight; 13765 i.railYRatio = i.containerHeight / i.railYHeight; 13766 i.scrollbarYHeight = getThumbSize( 13767 i, 13768 toInt(i.railYHeight * i.containerHeight / i.contentHeight) 13769 ); 13770 i.scrollbarYTop = toInt( 13771 roundedScrollTop * 13772 (i.railYHeight - i.scrollbarYHeight) / 13773 (i.contentHeight - i.containerHeight) 13774 ); 13775 } else { 13776 i.scrollbarYActive = false; 13777 } 13778 13779 if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) { 13780 i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth; 13781 } 13782 if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) { 13783 i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight; 13784 } 13785 13786 updateCss(element, i); 13787 13788 if (i.scrollbarXActive) { 13789 element.classList.add(cls.state.active('x')); 13790 } else { 13791 element.classList.remove(cls.state.active('x')); 13792 i.scrollbarXWidth = 0; 13793 i.scrollbarXLeft = 0; 13794 element.scrollLeft = 0; 13795 } 13796 if (i.scrollbarYActive) { 13797 element.classList.add(cls.state.active('y')); 13798 } else { 13799 element.classList.remove(cls.state.active('y')); 13800 i.scrollbarYHeight = 0; 13801 i.scrollbarYTop = 0; 13802 element.scrollTop = 0; 13803 } 13804}; 13805 13806function getThumbSize(i, thumbSize) { 13807 if (i.settings.minScrollbarLength) { 13808 thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength); 13809 } 13810 if (i.settings.maxScrollbarLength) { 13811 thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength); 13812 } 13813 return thumbSize; 13814} 13815 13816function updateCss(element, i) { 13817 var xRailOffset = { width: i.railXWidth }; 13818 var roundedScrollTop = Math.floor(element.scrollTop); 13819 13820 if (i.isRtl) { 13821 xRailOffset.left = 13822 i.negativeScrollAdjustment + 13823 element.scrollLeft + 13824 i.containerWidth - 13825 i.contentWidth; 13826 } else { 13827 xRailOffset.left = element.scrollLeft; 13828 } 13829 if (i.isScrollbarXUsingBottom) { 13830 xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop; 13831 } else { 13832 xRailOffset.top = i.scrollbarXTop + roundedScrollTop; 13833 } 13834 set(i.scrollbarXRail, xRailOffset); 13835 13836 var yRailOffset = { top: roundedScrollTop, height: i.railYHeight }; 13837 if (i.isScrollbarYUsingRight) { 13838 if (i.isRtl) { 13839 yRailOffset.right = 13840 i.contentWidth - 13841 (i.negativeScrollAdjustment + element.scrollLeft) - 13842 i.scrollbarYRight - 13843 i.scrollbarYOuterWidth; 13844 } else { 13845 yRailOffset.right = i.scrollbarYRight - element.scrollLeft; 13846 } 13847 } else { 13848 if (i.isRtl) { 13849 yRailOffset.left = 13850 i.negativeScrollAdjustment + 13851 element.scrollLeft + 13852 i.containerWidth * 2 - 13853 i.contentWidth - 13854 i.scrollbarYLeft - 13855 i.scrollbarYOuterWidth; 13856 } else { 13857 yRailOffset.left = i.scrollbarYLeft + element.scrollLeft; 13858 } 13859 } 13860 set(i.scrollbarYRail, yRailOffset); 13861 13862 set(i.scrollbarX, { 13863 left: i.scrollbarXLeft, 13864 width: i.scrollbarXWidth - i.railBorderXWidth, 13865 }); 13866 set(i.scrollbarY, { 13867 top: i.scrollbarYTop, 13868 height: i.scrollbarYHeight - i.railBorderYWidth, 13869 }); 13870} 13871 13872var clickRail = function(i) { 13873 i.event.bind(i.scrollbarY, 'mousedown', function (e) { return e.stopPropagation(); }); 13874 i.event.bind(i.scrollbarYRail, 'mousedown', function (e) { 13875 var positionTop = 13876 e.pageY - 13877 window.pageYOffset - 13878 i.scrollbarYRail.getBoundingClientRect().top; 13879 var direction = positionTop >
vendor: 6,750 bytes, lines 13879-14150
13879 i.scrollbarYTop ? 1 : -1; 13880 13881 i.element.scrollTop += direction * i.containerHeight; 13882 updateGeometry(i); 13883 13884 e.stopPropagation(); 13885 }); 13886 13887 i.event.bind(i.scrollbarX, 'mousedown', function (e) { return e.stopPropagation(); }); 13888 i.event.bind(i.scrollbarXRail, 'mousedown', function (e) { 13889 var positionLeft = 13890 e.pageX - 13891 window.pageXOffset - 13892 i.scrollbarXRail.getBoundingClientRect().left; 13893 var direction = positionLeft > i.scrollbarXLeft ? 1 : -1; 13894 13895 i.element.scrollLeft += direction * i.containerWidth; 13896 updateGeometry(i); 13897 13898 e.stopPropagation(); 13899 }); 13900}; 13901 13902var dragThumb = function(i) { 13903 bindMouseScrollHandler(i, [ 13904 'containerWidth', 13905 'contentWidth', 13906 'pageX', 13907 'railXWidth', 13908 'scrollbarX', 13909 'scrollbarXWidth', 13910 'scrollLeft', 13911 'x', 13912 'scrollbarXRail' ]); 13913 bindMouseScrollHandler(i, [ 13914 'containerHeight', 13915 'contentHeight', 13916 'pageY', 13917 'railYHeight', 13918 'scrollbarY', 13919 'scrollbarYHeight', 13920 'scrollTop', 13921 'y', 13922 'scrollbarYRail' ]); 13923}; 13924 13925function bindMouseScrollHandler( 13926 i, 13927 ref 13928) { 13929 var containerHeight = ref[0]; 13930 var contentHeight = ref[1]; 13931 var pageY = ref[2]; 13932 var railYHeight = ref[3]; 13933 var scrollbarY = ref[4]; 13934 var scrollbarYHeight = ref[5]; 13935 var scrollTop = ref[6]; 13936 var y = ref[7]; 13937 var scrollbarYRail = ref[8]; 13938 13939 var element = i.element; 13940 13941 var startingScrollTop = null; 13942 var startingMousePageY = null; 13943 var scrollBy = null; 13944 13945 function mouseMoveHandler(e) { 13946 element[scrollTop] = 13947 startingScrollTop + scrollBy * (e[pageY] - startingMousePageY); 13948 addScrollingClass(i, y); 13949 updateGeometry(i); 13950 13951 e.stopPropagation(); 13952 e.preventDefault(); 13953 } 13954 13955 function mouseUpHandler() { 13956 removeScrollingClass(i, y); 13957 i[scrollbarYRail].classList.remove(cls.state.clicking); 13958 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); 13959 } 13960 13961 i.event.bind(i[scrollbarY], 'mousedown', function (e) { 13962 startingScrollTop = element[scrollTop]; 13963 startingMousePageY = e[pageY]; 13964 scrollBy = 13965 (i[contentHeight] - i[containerHeight]) / 13966 (i[railYHeight] - i[scrollbarYHeight]); 13967 13968 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); 13969 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); 13970 13971 i[scrollbarYRail].classList.add(cls.state.clicking); 13972 13973 e.stopPropagation(); 13974 e.preventDefault(); 13975 }); 13976} 13977 13978var keyboard = function(i) { 13979 var element = i.element; 13980 13981 var elementHovered = function () { return matches(element, ':hover'); }; 13982 var scrollbarFocused = function () { return matches(i.scrollbarX, ':focus') || matches(i.scrollbarY, ':focus'); }; 13983 13984 function shouldPreventDefault(deltaX, deltaY) { 13985 var scrollTop = Math.floor(element.scrollTop); 13986 if (deltaX === 0) { 13987 if (!i.scrollbarYActive) { 13988 return false; 13989 } 13990 if ( 13991 (scrollTop === 0 && deltaY > 0) || 13992 (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0) 13993 ) { 13994 return !i.settings.wheelPropagation; 13995 } 13996 } 13997 13998 var scrollLeft = element.scrollLeft; 13999 if (deltaY === 0) { 14000 if (!i.scrollbarXActive) { 14001 return false; 14002 } 14003 if ( 14004 (scrollLeft === 0 && deltaX < 0) || 14005 (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0) 14006 ) { 14007 return !i.settings.wheelPropagation; 14008 } 14009 } 14010 return true; 14011 } 14012 14013 i.event.bind(i.ownerDocument, 'keydown', function (e) { 14014 if ( 14015 (e.isDefaultPrevented && e.isDefaultPrevented()) || 14016 e.defaultPrevented 14017 ) { 14018 return; 14019 } 14020 14021 if (!elementHovered() && !scrollbarFocused()) { 14022 return; 14023 } 14024 14025 var activeElement = document.activeElement 14026 ? document.activeElement 14027 : i.ownerDocument.activeElement; 14028 if (activeElement) { 14029 if (activeElement.tagName === 'IFRAME') { 14030 activeElement = activeElement.contentDocument.activeElement; 14031 } else { 14032 // go deeper if element is a webcomponent 14033 while (activeElement.shadowRoot) { 14034 activeElement = activeElement.shadowRoot.activeElement; 14035 } 14036 } 14037 if (isEditable(activeElement)) { 14038 return; 14039 } 14040 } 14041 14042 var deltaX = 0; 14043 var deltaY = 0; 14044 14045 switch (e.which) { 14046 case 37: // left 14047 if (e.metaKey) { 14048 deltaX = -i.contentWidth; 14049 } else if (e.altKey) { 14050 deltaX = -i.containerWidth; 14051 } else { 14052 deltaX = -30; 14053 } 14054 break; 14055 case 38: // up 14056 if (e.metaKey) { 14057 deltaY = i.contentHeight; 14058 } else if (e.altKey) { 14059 deltaY = i.containerHeight; 14060 } else { 14061 deltaY = 30; 14062 } 14063 break; 14064 case 39: // right 14065 if (e.metaKey) { 14066 deltaX = i.contentWidth; 14067 } else if (e.altKey) { 14068 deltaX = i.containerWidth; 14069 } else { 14070 deltaX = 30; 14071 } 14072 break; 14073 case 40: // down 14074 if (e.metaKey) { 14075 deltaY = -i.contentHeight; 14076 } else if (e.altKey) { 14077 deltaY = -i.containerHeight; 14078 } else { 14079 deltaY = -30; 14080 } 14081 break; 14082 case 32: // space bar 14083 if (e.shiftKey) { 14084 deltaY = i.containerHeight; 14085 } else { 14086 deltaY = -i.containerHeight; 14087 } 14088 break; 14089 case 33: // page up 14090 deltaY = i.containerHeight; 14091 break; 14092 case 34: // page down 14093 deltaY = -i.containerHeight; 14094 break; 14095 case 36: // home 14096 deltaY = i.contentHeight; 14097 break; 14098 case 35: // end 14099 deltaY = -i.contentHeight; 14100 break; 14101 default: 14102 return; 14103 } 14104 14105 if (i.settings.suppressScrollX && deltaX !== 0) { 14106 return; 14107 } 14108 if (i.settings.suppressScrollY && deltaY !== 0) { 14109 return; 14110 } 14111 14112 element.scrollTop -= deltaY; 14113 element.scrollLeft += deltaX; 14114 updateGeometry(i); 14115 14116 if (shouldPreventDefault(deltaX, deltaY)) { 14117 e.preventDefault(); 14118 } 14119 }); 14120}; 14121 14122var wheel = function(i) { 14123 var element = i.element; 14124 14125 function shouldPreventDefault(deltaX, deltaY) { 14126 var roundedScrollTop = Math.floor(element.scrollTop); 14127 var isTop = element.scrollTop === 0; 14128 var isBottom = 14129 roundedScrollTop + element.offsetHeight === element.scrollHeight; 14130 var isLeft = element.scrollLeft === 0; 14131 var isRight = 14132 element.scrollLeft + element.offsetWidth === element.scrollWidth; 14133 14134 var hitsBound; 14135 14136 // pick axis with primary direction 14137 if (Math.abs(deltaY) > Math.abs(deltaX)) { 14138 hitsBound = isTop || isBottom; 14139 } else { 14140 hitsBound = isLeft || isRight; 14141 } 14142 14143 return hitsBound ? !i.settings.wheelPropagation : true; 14144 } 14145 14146 function getDeltaFromEvent(e) { 14147 var deltaX = e.deltaX; 14148 var deltaY = -1 * e.deltaY; 14149 14150 if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
vendor: 10,958 bytes, lines 14151-14558
14151 // OS X Safari 14152 deltaX = -1 * e.wheelDeltaX / 6; 14153 deltaY = e.wheelDeltaY / 6; 14154 } 14155 14156 if (e.deltaMode && e.deltaMode === 1) { 14157 // Firefox in deltaMode 1: Line scrolling 14158 deltaX *= 10; 14159 deltaY *= 10; 14160 } 14161 14162 if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) { 14163 // IE in some mouse drivers 14164 deltaX = 0; 14165 deltaY = e.wheelDelta; 14166 } 14167 14168 if (e.shiftKey) { 14169 // reverse axis with shift key 14170 return [-deltaY, -deltaX]; 14171 } 14172 return [deltaX, deltaY]; 14173 } 14174 14175 function shouldBeConsumedByChild(target, deltaX, deltaY) { 14176 // FIXME: this is a workaround for <select> issue in FF and IE #571 14177 if (!env.isWebKit && element.querySelector('select:focus')) { 14178 return true; 14179 } 14180 14181 if (!element.contains(target)) { 14182 return false; 14183 } 14184 14185 var cursor = target; 14186 14187 while (cursor && cursor !== element) { 14188 if (cursor.classList.contains(cls.element.consuming)) { 14189 return true; 14190 } 14191 14192 var style = get(cursor); 14193 var overflow = [style.overflow, style.overflowX, style.overflowY].join( 14194 '' 14195 ); 14196 14197 // if scrollable 14198 if (overflow.match(/(scroll|auto)/)) { 14199 var maxScrollTop = cursor.scrollHeight - cursor.clientHeight; 14200 if (maxScrollTop > 0) { 14201 if ( 14202 !(cursor.scrollTop === 0 && deltaY > 0) && 14203 !(cursor.scrollTop === maxScrollTop && deltaY < 0) 14204 ) { 14205 return true; 14206 } 14207 } 14208 var maxScrollLeft = cursor.scrollWidth - cursor.clientWidth; 14209 if (maxScrollLeft > 0) { 14210 if ( 14211 !(cursor.scrollLeft === 0 && deltaX < 0) && 14212 !(cursor.scrollLeft === maxScrollLeft && deltaX > 0) 14213 ) { 14214 return true; 14215 } 14216 } 14217 } 14218 14219 cursor = cursor.parentNode; 14220 } 14221 14222 return false; 14223 } 14224 14225 function mousewheelHandler(e) { 14226 var ref = getDeltaFromEvent(e); 14227 var deltaX = ref[0]; 14228 var deltaY = ref[1]; 14229 14230 if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) { 14231 return; 14232 } 14233 14234 var shouldPrevent = false; 14235 if (!i.settings.useBothWheelAxes) { 14236 // deltaX will only be used for horizontal scrolling and deltaY will 14237 // only be used for vertical scrolling - this is the default 14238 element.scrollTop -= deltaY * i.settings.wheelSpeed; 14239 element.scrollLeft += deltaX * i.settings.wheelSpeed; 14240 } else if (i.scrollbarYActive && !i.scrollbarXActive) { 14241 // only vertical scrollbar is active and useBothWheelAxes option is 14242 // active, so let's scroll vertical bar using both mouse wheel axes 14243 if (deltaY) { 14244 element.scrollTop -= deltaY * i.settings.wheelSpeed; 14245 } else { 14246 element.scrollTop += deltaX * i.settings.wheelSpeed; 14247 } 14248 shouldPrevent = true; 14249 } else if (i.scrollbarXActive && !i.scrollbarYActive) { 14250 // useBothWheelAxes and only horizontal bar is active, so use both 14251 // wheel axes for horizontal bar 14252 if (deltaX) { 14253 element.scrollLeft += deltaX * i.settings.wheelSpeed; 14254 } else { 14255 element.scrollLeft -= deltaY * i.settings.wheelSpeed; 14256 } 14257 shouldPrevent = true; 14258 } 14259 14260 updateGeometry(i); 14261 14262 shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY); 14263 if (shouldPrevent && !e.ctrlKey) { 14264 e.stopPropagation(); 14265 e.preventDefault(); 14266 } 14267 } 14268 14269 if (typeof window.onwheel !== 'undefined') { 14270 i.event.bind(element, 'wheel', mousewheelHandler); 14271 } else if (typeof window.onmousewheel !== 'undefined') { 14272 i.event.bind(element, 'mousewheel', mousewheelHandler); 14273 } 14274}; 14275 14276var touch = function(i) { 14277 if (!env.supportsTouch && !env.supportsIePointer) { 14278 return; 14279 } 14280 14281 var element = i.element; 14282 14283 function shouldPrevent(deltaX, deltaY) { 14284 var scrollTop = Math.floor(element.scrollTop); 14285 var scrollLeft = element.scrollLeft; 14286 var magnitudeX = Math.abs(deltaX); 14287 var magnitudeY = Math.abs(deltaY); 14288 14289 if (magnitudeY > magnitudeX) { 14290 // user is perhaps trying to swipe up/down the page 14291 14292 if ( 14293 (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) || 14294 (deltaY > 0 && scrollTop === 0) 14295 ) { 14296 // set prevent for mobile Chrome refresh 14297 return window.scrollY === 0 && deltaY > 0 && env.isChrome; 14298 } 14299 } else if (magnitudeX > magnitudeY) { 14300 // user is perhaps trying to swipe left/right across the page 14301 14302 if ( 14303 (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) || 14304 (deltaX > 0 && scrollLeft === 0) 14305 ) { 14306 return true; 14307 } 14308 } 14309 14310 return true; 14311 } 14312 14313 function applyTouchMove(differenceX, differenceY) { 14314 element.scrollTop -= differenceY; 14315 element.scrollLeft -= differenceX; 14316 14317 updateGeometry(i); 14318 } 14319 14320 var startOffset = {}; 14321 var startTime = 0; 14322 var speed = {}; 14323 var easingLoop = null; 14324 14325 function getTouch(e) { 14326 if (e.targetTouches) { 14327 return e.targetTouches[0]; 14328 } else { 14329 // Maybe IE pointer 14330 return e; 14331 } 14332 } 14333 14334 function shouldHandle(e) { 14335 if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) { 14336 return false; 14337 } 14338 if (e.targetTouches && e.targetTouches.length === 1) { 14339 return true; 14340 } 14341 if ( 14342 e.pointerType && 14343 e.pointerType !== 'mouse' && 14344 e.pointerType !== e.MSPOINTER_TYPE_MOUSE 14345 ) { 14346 return true; 14347 } 14348 return false; 14349 } 14350 14351 function touchStart(e) { 14352 if (!shouldHandle(e)) { 14353 return; 14354 } 14355 14356 var touch = getTouch(e); 14357 14358 startOffset.pageX = touch.pageX; 14359 startOffset.pageY = touch.pageY; 14360 14361 startTime = new Date().getTime(); 14362 14363 if (easingLoop !== null) { 14364 clearInterval(easingLoop); 14365 } 14366 } 14367 14368 function shouldBeConsumedByChild(target, deltaX, deltaY) { 14369 if (!element.contains(target)) { 14370 return false; 14371 } 14372 14373 var cursor = target; 14374 14375 while (cursor && cursor !== element) { 14376 if (cursor.classList.contains(cls.element.consuming)) { 14377 return true; 14378 } 14379 14380 var style = get(cursor); 14381 var overflow = [style.overflow, style.overflowX, style.overflowY].join( 14382 '' 14383 ); 14384 14385 // if scrollable 14386 if (overflow.match(/(scroll|auto)/)) { 14387 var maxScrollTop = cursor.scrollHeight - cursor.clientHeight; 14388 if (maxScrollTop > 0) { 14389 if ( 14390 !(cursor.scrollTop === 0 && deltaY > 0) && 14391 !(cursor.scrollTop === maxScrollTop && deltaY < 0) 14392 ) { 14393 return true; 14394 } 14395 } 14396 var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth; 14397 if (maxScrollLeft > 0) { 14398 if ( 14399 !(cursor.scrollLeft === 0 && deltaX < 0) && 14400 !(cursor.scrollLeft === maxScrollLeft && deltaX > 0) 14401 ) { 14402 return true; 14403 } 14404 } 14405 } 14406 14407 cursor = cursor.parentNode; 14408 } 14409 14410 return false; 14411 } 14412 14413 function touchMove(e) { 14414 if (shouldHandle(e)) { 14415 var touch = getTouch(e); 14416 14417 var currentOffset = { pageX: touch.pageX, pageY: touch.pageY }; 14418 14419 var differenceX = currentOffset.pageX - startOffset.pageX; 14420 var differenceY = currentOffset.pageY - startOffset.pageY; 14421 14422 if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) { 14423 return; 14424 } 14425 14426 applyTouchMove(differenceX, differenceY); 14427 startOffset = currentOffset; 14428 14429 var currentTime = new Date().getTime(); 14430 14431 var timeGap = currentTime - startTime; 14432 if (timeGap > 0) { 14433 speed.x = differenceX / timeGap; 14434 speed.y = differenceY / timeGap; 14435 startTime = currentTime; 14436 } 14437 14438 if (shouldPrevent(differenceX, differenceY)) { 14439 e.preventDefault(); 14440 } 14441 } 14442 } 14443 function touchEnd() { 14444 if (i.settings.swipeEasing) { 14445 clearInterval(easingLoop); 14446 easingLoop = setInterval(function() { 14447 if (i.isInitialized) { 14448 clearInterval(easingLoop); 14449 return; 14450 } 14451 14452 if (!speed.x && !speed.y) { 14453 clearInterval(easingLoop); 14454 return; 14455 } 14456 14457 if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { 14458 clearInterval(easingLoop); 14459 return; 14460 } 14461 14462 applyTouchMove(speed.x * 30, speed.y * 30); 14463 14464 speed.x *= 0.8; 14465 speed.y *= 0.8; 14466 }, 10); 14467 } 14468 } 14469 14470 if (env.supportsTouch) { 14471 i.event.bind(element, 'touchstart', touchStart); 14472 i.event.bind(element, 'touchmove', touchMove); 14473 i.event.bind(element, 'touchend', touchEnd); 14474 } else if (env.supportsIePointer) { 14475 if (window.PointerEvent) { 14476 i.event.bind(element, 'pointerdown', touchStart); 14477 i.event.bind(element, 'pointermove', touchMove); 14478 i.event.bind(element, 'pointerup', touchEnd); 14479 } else if (window.MSPointerEvent) { 14480 i.event.bind(element, 'MSPointerDown', touchStart); 14481 i.event.bind(element, 'MSPointerMove', touchMove); 14482 i.event.bind(element, 'MSPointerUp', touchEnd); 14483 } 14484 } 14485}; 14486 14487var defaultSettings = function () { return ({ 14488 handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'], 14489 maxScrollbarLength: null, 14490 minScrollbarLength: null, 14491 scrollingThreshold: 1000, 14492 scrollXMarginOffset: 0, 14493 scrollYMarginOffset: 0, 14494 suppressScrollX: false, 14495 suppressScrollY: false, 14496 swipeEasing: true, 14497 useBothWheelAxes: false, 14498 wheelPropagation: true, 14499 wheelSpeed: 1, 14500}); }; 14501 14502var handlers = { 14503 'click-rail': clickRail, 14504 'drag-thumb': dragThumb, 14505 keyboard: keyboard, 14506 wheel: wheel, 14507 touch: touch, 14508}; 14509 14510var PerfectScrollbar = function PerfectScrollbar(element, userSettings) { 14511 var this$1 = this; 14512 if ( userSettings === void 0 ) userSettings = {}; 14513 14514 if (typeof element === 'string') { 14515 element = document.querySelector(element); 14516 } 14517 14518 if (!element || !element.nodeName) { 14519 throw new Error('no element is specified to initialize PerfectScrollbar'); 14520 } 14521 14522 this.element = element; 14523 14524 element.classList.add(cls.main); 14525 14526 this.settings = defaultSettings(); 14527 for (var key in userSettings) { 14528 this$1.settings[key] = userSettings[key]; 14529 } 14530 14531 this.containerWidth = null; 14532 this.containerHeight = null; 14533 this.contentWidth = null; 14534 this.contentHeight = null; 14535 14536 var focus = function () { return element.classList.add(cls.state.focus); }; 14537 var blur = function () { return element.classList.remove(cls.state.focus); }; 14538 14539 this.isRtl = get(element).direction === 'rtl'; 14540 this.isNegativeScroll = (function () { 14541 var originalScrollLeft = element.scrollLeft; 14542 var result = null; 14543 element.scrollLeft = -1; 14544 result = element.scrollLeft < 0; 14545 element.scrollLeft = originalScrollLeft; 14546 return result; 14547 })(); 14548 this.negativeScrollAdjustment = this.isNegativeScroll 14549 ? element.scrollWidth - element.clientWidth 14550 : 0; 14551 this.event = new EventManager(); 14552 this.ownerDocument = element.ownerDocument || document; 14553 14554 this.scrollbarXRail = div(cls.element.rail('x')); 14555 element.appendChild(this.scrollbarXRail); 14556 this.scrollbarX = div(cls.element.thumb('x')); 14557 this.scrollbarXRail.appendChild(this.scrollbarX); 14558 this.scrollbarX.setAttribute('tabindex', 0);
vendor: 4,650 bytes, lines 14559-14704
14559 this.event.bind(this.scrollbarX, 'focus', focus); 14560 this.event.bind(this.scrollbarX, 'blur', blur); 14561 this.scrollbarXActive = null; 14562 this.scrollbarXWidth = null; 14563 this.scrollbarXLeft = null; 14564 var railXStyle = get(this.scrollbarXRail); 14565 this.scrollbarXBottom = parseInt(railXStyle.bottom, 10); 14566 if (isNaN(this.scrollbarXBottom)) { 14567 this.isScrollbarXUsingBottom = false; 14568 this.scrollbarXTop = toInt(railXStyle.top); 14569 } else { 14570 this.isScrollbarXUsingBottom = true; 14571 } 14572 this.railBorderXWidth = 14573 toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth); 14574 // Set rail to display:block to calculate margins 14575 set(this.scrollbarXRail, { display: 'block' }); 14576 this.railXMarginWidth = 14577 toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight); 14578 set(this.scrollbarXRail, { display: '' }); 14579 this.railXWidth = null; 14580 this.railXRatio = null; 14581 14582 this.scrollbarYRail = div(cls.element.rail('y')); 14583 element.appendChild(this.scrollbarYRail); 14584 this.scrollbarY = div(cls.element.thumb('y')); 14585 this.scrollbarYRail.appendChild(this.scrollbarY); 14586 this.scrollbarY.setAttribute('tabindex', 0); 14587 this.event.bind(this.scrollbarY, 'focus', focus); 14588 this.event.bind(this.scrollbarY, 'blur', blur); 14589 this.scrollbarYActive = null; 14590 this.scrollbarYHeight = null; 14591 this.scrollbarYTop = null; 14592 var railYStyle = get(this.scrollbarYRail); 14593 this.scrollbarYRight = parseInt(railYStyle.right, 10); 14594 if (isNaN(this.scrollbarYRight)) { 14595 this.isScrollbarYUsingRight = false; 14596 this.scrollbarYLeft = toInt(railYStyle.left); 14597 } else { 14598 this.isScrollbarYUsingRight = true; 14599 } 14600 this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null; 14601 this.railBorderYWidth = 14602 toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth); 14603 set(this.scrollbarYRail, { display: 'block' }); 14604 this.railYMarginHeight = 14605 toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom); 14606 set(this.scrollbarYRail, { display: '' }); 14607 this.railYHeight = null; 14608 this.railYRatio = null; 14609 14610 this.reach = { 14611 x: 14612 element.scrollLeft <= 0 14613 ? 'start' 14614 : element.scrollLeft >= this.contentWidth - this.containerWidth 14615 ? 'end' 14616 : null, 14617 y: 14618 element.scrollTop <= 0 14619 ? 'start' 14620 : element.scrollTop >= this.contentHeight - this.containerHeight 14621 ? 'end' 14622 : null, 14623 }; 14624 14625 this.isAlive = true; 14626 14627 this.settings.handlers.forEach(function (handlerName) { return handlers[handlerName](this$1); }); 14628 14629 this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only 14630 this.lastScrollLeft = element.scrollLeft; // for onScroll only 14631 this.event.bind(this.element, 'scroll', function (e) { return this$1.onScroll(e); }); 14632 updateGeometry(this); 14633}; 14634 14635PerfectScrollbar.prototype.update = function update () { 14636 if (!this.isAlive) { 14637 return; 14638 } 14639 14640 // Recalcuate negative scrollLeft adjustment 14641 this.negativeScrollAdjustment = this.isNegativeScroll 14642 ? this.element.scrollWidth - this.element.clientWidth 14643 : 0; 14644 14645 // Recalculate rail margins 14646 set(this.scrollbarXRail, { display: 'block' }); 14647 set(this.scrollbarYRail, { display: 'block' }); 14648 this.railXMarginWidth = 14649 toInt(get(this.scrollbarXRail).marginLeft) + 14650 toInt(get(this.scrollbarXRail).marginRight); 14651 this.railYMarginHeight = 14652 toInt(get(this.scrollbarYRail).marginTop) + 14653 toInt(get(this.scrollbarYRail).marginBottom); 14654 14655 // Hide scrollbars not to affect scrollWidth and scrollHeight 14656 set(this.scrollbarXRail, { display: 'none' }); 14657 set(this.scrollbarYRail, { display: 'none' }); 14658 14659 updateGeometry(this); 14660 14661 processScrollDiff(this, 'top', 0, false, true); 14662 processScrollDiff(this, 'left', 0, false, true); 14663 14664 set(this.scrollbarXRail, { display: '' }); 14665 set(this.scrollbarYRail, { display: '' }); 14666}; 14667 14668PerfectScrollbar.prototype.onScroll = function onScroll (e) { 14669 if (!this.isAlive) { 14670 return; 14671 } 14672 14673 updateGeometry(this); 14674 processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop); 14675 processScrollDiff( 14676 this, 14677 'left', 14678 this.element.scrollLeft - this.lastScrollLeft 14679 ); 14680 14681 this.lastScrollTop = Math.floor(this.element.scrollTop); 14682 this.lastScrollLeft = this.element.scrollLeft; 14683}; 14684 14685PerfectScrollbar.prototype.destroy = function destroy () { 14686 if (!this.isAlive) { 14687 return; 14688 } 14689 14690 this.event.unbindAll(); 14691 remove(this.scrollbarX); 14692 remove(this.scrollbarY); 14693 remove(this.scrollbarXRail); 14694 remove(this.scrollbarYRail); 14695 this.removePsClasses(); 14696 14697 // unset elements 14698 this.element = null; 14699 this.scrollbarX = null; 14700 this.scrollbarY = null; 14701 this.scrollbarXRail = null; 14702 this.scrollbarYRail = null; 14703 14704 this.isAlive = false;
14705}; 14706 14707PerfectScrollbar.prototype.removePsClasses = function removePsClasses () { 14708 this.element.className = this.element.className 14709 .split(' ') 14710 .filter(function (name) { return !name.match(/^ps([-_].+|)$/); }) 14711 .join(' '); 14712}; 14713 14714return PerfectScrollbar; 14715 14716}))); 14717 14718function _classCallCheck(t,i){if(!(t instanceof i))throw new TypeError("Cannot call a class as a function")}var Sticky=function(){function t(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};_classCallCheck(this,t),this.selector=i,this.elements=[],this.version="1.2.0",this.vp=this.getViewportSize(),this.body=document.querySelector("body"),this.options={wrap:e.wrap||!1,marginTop:e.marginTop||0,stickyFor:e.stickyFor||0,stickyClass:e.stickyClass||null,stickyContainer:e.stickyContainer||"body"},this.updateScrollTopPosition=this.updateScrollTopPosition.bind(this),this.updateScrollTopPosition(),window.addEventListener("load",this.updateScrollTopPosition),window.addEventListener("scroll",this.updateScrollTopPosition),this.run()}return t.prototype.run=function(){var t=this,i=setInterval(function(){if("complete"===document.readyState){clearInterval(i);var e=document.querySelectorAll(t.selector);t.forEach(e,function(i){return t.renderElement(i)})}},10)},t.prototype.renderElement=function(t){var i=this;t.sticky={},t.sticky.active=!1,t.sticky.marginTop=parseInt(t.getAttribute("data-margin-top"))||this.options.marginTop,t.sticky.stickyFor=parseInt(t.getAttribute("data-sticky-for"))||this.options.stickyFor,t.sticky.stickyClass=t.getAttribute("data-sticky-class")||this.options.stickyClass,t.sticky.wrap=!!t.hasAttribute("data-sticky-wrap")||this.options.wrap,t.sticky.stickyContainer=this.options.stickyContainer,t.sticky.container=this.getStickyContainer(t),t.sticky.container.rect=this.getRectangle(t.sticky.container),t.sticky.rect=this.getRectangle(t),"img"===t.tagName.toLowerCase()&&(t.onload=function(){return t.sticky.rect=i.getRectangle(t)}),t.sticky.wrap&&this.wrapElement(t),this.activate(t)},t.prototype.wrapElement=function(t){t.insertAdjacentHTML("beforebegin","<span></span>"),t.previousSibling.appendChild(t)},t.prototype.activate=function(t){t.sticky.rect.top+t.sticky.rect.height<t.sticky.container.rect.top+t.sticky.container.rect.height&&t.sticky.stickyFor<this.vp.width&&!t.sticky.active&&(t.sticky.active=!0),this.elements.indexOf(t)<0&&this.elements.push(t),t.sticky.resizeEvent||(this.initResizeEvents(t),t.sticky.resizeEvent=!0),t.sticky.scrollEvent||(this.initScrollEvents(t),t.sticky.scrollEvent=!0),this.setPosition(t)},t.prototype.initResizeEvents=function(t){var i=this;t.sticky.resizeListener=function(){return i.onResizeEvents(t)},window.addEventListener("resize",t.sticky.resizeListener)},t.prototype.destroyResizeEvents=function(t){window.removeEventListener("resize",t.sticky.resizeListener)},t.prototype.onResizeEvents=function(t){this.vp=this.getViewportSize(),t.sticky.rect=this.getRectangle(t),t.sticky.container.rect=this.getRectangle(t.sticky.container),t.sticky.rect.top+t.sticky.rect.height<t.sticky.container.rect.top+t.sticky.container.rect.height&&t.sticky.stickyFor<this.vp.width&&!t.sticky.active?t.sticky.active=!0:(t.sticky.rect.top+t.sticky.rect.height>=t.sticky.container.rect.top+t.sticky.container.rect.height||t.sticky.stickyFor>=this.vp.width&&t.sticky.active)&&(t.sticky.active=!1),this.setPosition(t)},t.prototype.initScrollEvents=function(t){var i=this;t.sticky.scrollListener=function(){return i.onScrollEvents(t)},window.addEventListener("scroll",t.sticky.scrollListener)},t.prototype.destroyScrollEvents=function(t){window.removeEventListener("scroll",t.sticky.scrollListener)},t.prototype.onScrollEvents=function(t){t.sticky.active&&this.setPosition(t)},t.prototype.setPosition=function(t){this.css(t,{position:"",width:"",top:"",left:""}),this.vp.height<t.sticky.rect.height||!t.sticky.active||(t.sticky.rect.width||(t.sticky.rect=this.getRectangle(t)),t.sticky.wrap&&this.css(t.parentNode,{display:"block",width:t.sticky.rect.width+"px",height:t.sticky.rect.height+"px"}),0===t.sticky.rect.top&&t.sticky.container===this.body?this.css(t,{position:"fixed",top:t.sticky.rect.top+"px",left:t.sticky.rect.left+"px",width:t.sticky.rect.width+"px"}):this.scrollTop>t.sticky.rect.top-t.sticky.marginTop?(this.css(t,{position:"fixed",width:t.sticky.rect.width+"px",left:t.sticky.rect.left+"px"}),this.scrollTop+t.sticky.rect.height+t.sticky.marginTop>t.sticky.container.rect.top+t.sticky.container.offsetHeight?(t.sticky.stickyClass&&t.classList.remove(t.sticky.stickyClass),this.css(t,{top:t.sticky.container.rect.top+t.sticky.container.offsetHeight-(this.scrollTop+t.sticky.rect.height)+"px"})):(t.sticky.stickyClass&&t.classList.add(t.sticky.stickyClass),this.css(t,{top:t.sticky.marginTop+"px"}))):(t.sticky.stickyClass&&t.classList.remove(t.sticky.stickyClass),this.css(t,{position:"",width:"",top:"",left:""}),t.sticky.wrap&&this.css(t.parentNode,{display:"",width:"",height:""})))},t.prototype.update=function(){var t=this;this.forEach(this.elements,function(i){i.sticky.rect=t.getRectangle(i),i.sticky.container.rect=t.getRectangle(i.sticky.container),t.activate(i),t.setPosition(i)})},t.prototype.destroy=function(){var t=this;this.forEach(this.elements,function(i){t.destroyResizeEvents(i),t.destroyScrollEvents(i),delete i.sticky})},t.prototype.getStickyContainer=function(t){for(var i=t.parentNode;!i.hasAttribute("data-sticky-container")&&!i.parentNode.querySelector(t.sticky.stickyContainer)&&i!==this.body;)i=i.parentNode;return i},t.prototype.getRectangle=function(t){this.css(t,{position:"",width:"",top:"",left:""});var i=Math.max(t.offsetWidth,t.clientWidth,t.scrollWidth),e=Math.max(t.offsetHeight,t.clientHeight,t.scrollHeight),s=0,o=0;do s+=t.offsetTop||0,o+=t.offsetLeft||0,t=t.offsetParent;while(t);return{top:s,left:o,width:i,height:e}},t.prototype.getViewportSize=function(){return{width:Math.max(document.documentElement.clientWidth,window.innerWidth||0),height:Math.max(document.documentElement.clientHeight,window.innerHeight||0)}},t.prototype.updateScrollTopPosition=function(){this.scrollTop=(window.pageYOffset||document.scrollTop)-(document.clientTop||0)||0},t.prototype.forEach=function(t,i){for(var e=0,s=t.length;e<s;e++)i(t[e])},t.prototype.css=function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t.style[e]=i[e])},t}();!function(t,i){"undefined"!=typeof exports?module.exports=i:"function"==typeof define&&define.amd?define([],i):t.Sticky=i}(this,Sticky); 14719(function (factory) { 14720 14721 if ( typeof define === 'function' && define.amd ) { 14722 14723 // AMD. Register as an anonymous module. 14724 define([], factory); 14725 14726 } else if ( typeof exports === 'object' ) { 14727 14728 // Node/CommonJS 14729 module.exports = factory(); 14730 14731 } else { 14732 14733 // Browser globals 14734 window.wNumb = factory(); 14735 } 14736 14737}(function(){ 14738 14739 'use strict'; 14740 14741var FormatOptions = [ 14742 'decimals', 14743 'thousand', 14744 'mark', 14745 'prefix', 14746 'suffix', 14747 'encoder', 14748 'decoder', 14749 'negativeBefore', 14750 'negative', 14751 'edit', 14752 'undo' 14753]; 14754 14755// General 14756 14757 // Reverse a string 14758 function strReverse ( a ) { 14759 return a.split('').reverse().join(''); 14760 } 14761 14762 // Check if a string starts with a specified prefix. 14763 function strStartsWith ( input, match ) { 14764 return input.substring(0, match.length) === match; 14765 } 14766 14767 // Check is a string ends in a specified suffix. 14768 function strEndsWith ( input, match ) { 14769 return input.slice(-1 * match.length) === match; 14770 } 14771 14772 // Throw an error if formatting options are incompatible.
14773 function throwEqualError( F, a, b ) { 14774 if ( (F[a] || F[b]) && (F[a] === F[b]) ) { 14775 throw new Error(a); 14776 } 14777 } 14778 14779 // Check if a number is finite and not NaN 14780 function isValidNumber ( input ) { 14781 return typeof input === 'number' && isFinite( input ); 14782 } 14783 14784 // Provide rounding-accurate toFixed method. 14785 // Borrowed: http://stackoverflow.com/a/21323330/775265 14786 function toFixed ( value, exp ) { 14787 value = value.toString().split('e'); 14788 value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp))); 14789 value = value.toString().split('e'); 14790 return (+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))).toFixed(exp); 14791 } 14792 14793 14794// Formatting 14795 14796 // Accept a number as input, output formatted string. 14797 function formatTo ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { 14798 14799 var originalInput = input, inputIsNegative, inputPieces, inputBase, inputDecimals = '', output = ''; 14800 14801 // Apply user encoder to the input. 14802 // Expected outcome: number. 14803 if ( encoder ) { 14804 input = encoder(input); 14805 } 14806 14807 // Stop if no valid number was provided, the number is infinite or NaN. 14808 if ( !isValidNumber(input) ) { 14809 return false; 14810 } 14811 14812 // Rounding away decimals might cause a value of -0 14813 // when using very small ranges. Remove those cases. 14814 if ( decimals !== false && parseFloat(input.toFixed(decimals)) === 0 ) { 14815 input = 0; 14816 } 14817 14818 // Formatting is done on absolute numbers, 14819 // decorated by an optional negative symbol. 14820 if ( input < 0 ) { 14821 inputIsNegative = true; 14822 input = Math.abs(input); 14823 } 14824 14825 // Reduce the number of decimals to the specified option. 14826 if ( decimals !== false ) { 14827 input = toFixed( input, decimals ); 14828 } 14829 14830 // Transform the number into a string, so it can be split. 14831 input = input.toString(); 14832 14833 // Break the number on the decimal separator. 14834 if ( input.indexOf('.') !== -1 ) { 14835 inputPieces = input.split('.'); 14836 14837 inputBase = inputPieces[0]; 14838 14839 if ( mark ) { 14840 inputDecimals = mark + inputPieces[1]; 14841 } 14842 14843 } else { 14844 14845 // If it isn't split, the entire number will do. 14846 inputBase = input; 14847 } 14848 14849 // Group numbers in sets of three. 14850 if ( thousand ) { 14851 inputBase = strReverse(inputBase).match(/.{1,3}/g); 14852 inputBase = strReverse(inputBase.join( strReverse( thousand ) )); 14853 } 14854 14855 // If the number is negative, prefix with negation symbol. 14856 if ( inputIsNegative && negativeBefore ) { 14857 output += negativeBefore; 14858 } 14859 14860 // Prefix the number 14861 if ( prefix ) { 14862 output += prefix; 14863 } 14864 14865 // Normal negative option comes after the prefix. Defaults to '-'. 14866 if ( inputIsNegative && negative ) { 14867 output += negative; 14868 } 14869 14870 // Append the actual number. 14871 output += inputBase; 14872 output += inputDecimals; 14873 14874 // Apply the suffix. 14875 if ( suffix ) { 14876 output += suffix; 14877 } 14878 14879 // Run the output through a user-specified post-formatter. 14880 if ( edit ) { 14881 output = edit ( output, originalInput ); 14882 } 14883 14884 // All done. 14885 return output; 14886 } 14887 14888 // Accept a sting as input, output decoded number. 14889 function formatFrom ( decimals, thousand, mark, prefix, suffix, encoder, decoder, negativeBefore, negative, edit, undo, input ) { 14890 14891 var originalInput = input, inputIsNegative, output = ''; 14892 14893 // User defined pre-decoder. Result must be a non empty string. 14894 if ( undo ) { 14895 input = undo(input); 14896 } 14897 14898 // Test the input. Can't be empty. 14899 if ( !input || typeof input !== 'string' ) { 14900 return false; 14901 } 14902 14903 // If the string starts with the negativeBefore value: remove it. 14904 // Remember is was there, the number is negative. 14905 if ( negativeBefore && strStartsWith(input, negativeBefore) ) { 14906 input = input.replace(negativeBefore, ''); 14907 inputIsNegative = true; 14908 } 14909 14910 // Repeat the same procedure for the prefix. 14911 if ( prefix && strStartsWith(input, prefix) ) { 14912 input = input.replace(prefix, ''); 14913 } 14914 14915 // And again for negative. 14916 if ( negative && strStartsWith(input, negative) ) { 14917 input = input.replace(negative, ''); 14918 inputIsNegative = true; 14919 } 14920 14921 // Remove the suffix. 14922 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
14923 if ( suffix && strEndsWith(input, suffix) ) { 14924 input = input.slice(0, -1 * suffix.length); 14925 } 14926 14927 // Remove the thousand grouping. 14928 if ( thousand ) { 14929 input = input.split(thousand).join(''); 14930 } 14931 14932 // Set the decimal separator back to period. 14933 if ( mark ) { 14934 input = input.replace(mark, '.'); 14935 } 14936 14937 // Prepend the negative symbol. 14938 if ( inputIsNegative ) { 14939 output += '-'; 14940 } 14941 14942 // Add the number 14943 output += input; 14944 14945 // Trim all non-numeric characters (allow '.' and '-'); 14946 output = output.replace(/[^0-9\.\-.]/g, ''); 14947 14948 // The value contains no parse-able number. 14949 if ( output === '' ) { 14950 return false; 14951 } 14952 14953 // Covert to number. 14954 output = Number(output); 14955 14956 // Run the user-specified post-decoder. 14957 if ( decoder ) { 14958 output = decoder(output); 14959 } 14960 14961 // Check is the output is valid, otherwise: return false. 14962 if ( !isValidNumber(output) ) { 14963 return false; 14964 } 14965 14966 return output; 14967 } 14968 14969 14970// Framework 14971 14972 // Validate formatting options 14973 function validate ( inputOptions ) { 14974 14975 var i, optionName, optionValue, 14976 filteredOptions = {}; 14977 14978 if ( inputOptions['suffix'] === undefined ) { 14979 inputOptions['suffix'] = inputOptions['postfix']; 14980 } 14981 14982 for ( i = 0; i < FormatOptions.length; i+=1 ) { 14983 14984 optionName = FormatOptions[i]; 14985 optionValue = inputOptions[optionName]; 14986 14987 if ( optionValue === undefined ) { 14988 14989 // Only default if negativeBefore isn't set. 14990 if ( optionName === 'negative' && !filteredOptions.negativeBefore ) { 14991 filteredOptions[optionName] = '-'; 14992 // Don't set a default for mark when 'thousand' is set. 14993 } else if ( optionName === 'mark' && filteredOptions.thousand !== '.' ) { 14994 filteredOptions[optionName] = '.'; 14995 } else { 14996 filteredOptions[optionName] = false; 14997 } 14998 14999 // Floating points in JS are stable up to 7 decimals. 15000 } else if ( optionName === 'decimals' ) { 15001 if ( optionValue >= 0 && optionValue < 8 ) { 15002 filteredOptions[optionName] = optionValue; 15003 } else { 15004 throw new Error(optionName); 15005 } 15006 15007 // These options, when provided, must be functions. 15008 } else if ( optionName === 'encoder' || optionName === 'decoder' || optionName === 'edit' || optionName === 'undo' ) { 15009 if ( typeof optionValue === 'function' ) { 15010 filteredOptions[optionName] = optionValue; 15011 } else { 15012 throw new Error(optionName); 15013 } 15014 15015 // Other options are strings. 15016 } else { 15017 15018 if ( typeof optionValue === 'string' ) { 15019 filteredOptions[optionName] = optionValue; 15020 } else { 15021 throw new Error(optionName); 15022 } 15023 } 15024 } 15025 15026 // Some values can't be extracted from a 15027 // string if certain combinations are present. 15028 throwEqualError(filteredOptions, 'mark', 'thousand'); 15029 throwEqualError(filteredOptions, 'prefix', 'negative'); 15030 throwEqualError(filteredOptions, 'prefix', 'negativeBefore'); 15031 15032 return filteredOptions; 15033 } 15034 15035 // Pass all options as function arguments 15036 function passAll ( options, method, input ) { 15037 var i, args = []; 15038 15039 // Add all options in order of FormatOptions 15040 for ( i = 0; i < FormatOptions.length; i+=1 ) { 15041 args.push(options[FormatOptions[i]]); 15042 } 15043 15044 // Append the input, then call the method, presenting all 15045 // options as arguments. 15046 args.push(input); 15047 return method.apply('', args); 15048 } 15049 15050 function wNumb ( options ) { 15051 15052 if ( !(this instanceof wNumb) ) { 15053 return new wNumb ( options ); 15054 } 15055 15056 if ( typeof options !== "object" ) { 15057 return; 15058 } 15059 15060 options = validate(options); 15061 15062 // Call 'formatTo' with proper arguments. 15063 this.to = function ( input ) { 15064 return passAll(options, formatTo, input); 15065 }; 15066 15067 // Call 'formatFrom' with proper arguments. 15068 this.from = function ( input ) { 15069 return passAll(options, formatFrom, input); 15070 }; 15071 } 15072 15073 return wNumb; 15074 15075})); 15076 15077/*! 15078 * jQuery Form Plugin 15079 * version: 4.2.2 15080 * Requires jQuery v1.7.2 or later 15081 * Project repository: https://github.com/jquery-form/form 15082 15083 * Copyright 2017 Kevin Morris 15084 * Copyright 2006 M. Alsup 15085 15086 * Dual licensed under the LGPL-2.1+ or MIT licenses 15087 * https://github.com/jquery-form/form#license 15088 15089 * This library is free software; you can redistribute it and/or 15090 * modify it under the terms of the GNU Lesser General Public
15091 * License as published by the Free Software Foundation; either 15092 * version 2.1 of the License, or (at your option) any later version. 15093 * This library is distributed in the hope that it will be useful, 15094 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15095 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15096 * Lesser General Public License for more details. 15097 */ 15098!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,r){return void 0===r&&(r="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(r),r}:e(jQuery)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).closest("form").ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=r.form;if(i.clk=r,"image"===r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n=/\r?\n/g,i={};i.fileapi=void 0!==e('<input type="file">').get(0).files,i.formdata=void 0!==window.FormData;var o=!!e.fn.prop;e.fn.attr2=function(){if(!o)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t,r,n,s){function u(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;a<o;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function c(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(e){a("cannot get iframe.contentWindow document: "+e)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function i(){function t(){try{var e=n(v).readyState;a("state = "+e),e&&"uninitialized"===e.toLowerCase()&&setTimeout(t,50)}catch(e){a("Server abort: ",e," (",e.name,")"),s(L),j&&clearTimeout(j),j=void 0}}var r=p.attr2("target"),i=p.attr2("action"),o=p.attr("enctype")||p.attr("encoding")||"multipart/form-data";w.setAttribute("target",m),l&&!/post/i.test(l)||w.setAttribute("method","POST"),i!==f.url&&w.setAttribute("action",f.url),f.skipEncodingOverride||l&&!/post/i.test(l)||p.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),f.timeout&&(j=setTimeout(function(){T=!0,s(A)},f.timeout));var u=[];try{if(f.extraData)for(var c in f.extraData)f.extraData.hasOwnProperty(c)&&(e.isPlainObject(f.extraData[c])&&f.extraData[c].hasOwnProperty("name")&&f.extraData[c].hasOwnProperty("value")?u.push(e('<input type="hidden" name="'+f.extraData[c].name+'">',k).val(f.extraData[c].value).appendTo(w)[0]):u.push(e('<input type="hidden" name="'+c+'">',k).val(f.extraData[c]).appendTo(w)[0]));f.iframeTarget||h.appendTo(D),v.attachEvent?v.attachEvent("onload",s):v.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(e){document.createElement("form").submit.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",o),r?w.setAttribute("target",r):p.removeAttr("target"),e(u).remove()}}function s(t){if(!x.aborted&&!X){if((O=n(v))||(a("cannot access response document"),t=L),t===A&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t===L&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(O&&O.location.href!==f.iframeSrc||T){v.detachEvent?v.detachEvent("onload",s):v.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"===f.dataType||O.XMLDocument||e.isXMLDoc(O);if(a("isXml="+o),!o&&window.opera&&(null===O.body||!O.body.innerHTML)&&--C)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=O.body?O.body:O.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=O.XMLDocument?O.XMLDocument:O,o&&(f.dataType="xml"),x.getResponseHeader=function(e){return{"content-type":f.dataType}[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var c=(f.dataType||"").toLowerCase(),l=/(json|script|text)/.test(c);if(l||f.textarea){var p=O.getElementsByTagName("textarea")[0];if(p)x.responseText=p.value,x.status=Number(p.getAttribute("status"))||x.status,x.statusText=p.getAttribute("statusText")||x.statusText;else if(l){var m=O.getElementsByTagName("pre")[0],g=O.getElementsByTagName("body")[0];m?x.responseText=m.textContent?m.textContent:m.innerText:g&&(x.responseText=g.textContent?g.textContent:g.innerText)}}else"xml"===c&&!x.responseXML&&x.responseText&&(x.responseXML=q(x.responseText));try{M=N(x,c,f)}catch(e){i="parsererror",x.error=r=e||i}}catch(e){a("error caught: ",e),i="error",x.error=r=e||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&x.status<300||304===x.status?"success":"error"),"success"===i?(f.success&&f.success.call(f.context,M,"success",x),S.resolve(x.responseText,"success",x),d&&e.event.trigger("ajaxSuccess",[x,f])):i&&(void 0===r&&(r=x.statusText),f.error&&f.error.call(f.context,x,i,r),S.reject(x,"error",r),d&&e.event.trigger("ajaxError",[x,f,r])),d&&e.event.trigger("ajaxComplete",[x,f]),d&&!--e.active&&e.event.trigger("ajaxStop"),f.complete&&f.complete.call(f.context,x,i),X=!0,f.timeout&&clearTimeout(j),setTimeout(function(){f.iframeTarget?h.attr("src",f.iframeSrc):h.remove(),x.responseXML=null},100)}}}var u,c,f,d,m,h,v,x,y,b,T,j,w=p[0],S=e.Deferred();if(S.abort=function(e){x.abort(e)},r)for(c=0;c<g.length;c++)u=e(g[c]),o?u.prop("disabled",!1):u.removeAttr("disabled");(f=e.extend(!0,{},e.ajaxSettings,t)).context=f.context||f,m="jqFormIO"+(new Date).getTime();var k=w.ownerDocument,D=p.closest("body");if(f.iframeTarget?(b=(h=e(f.iframeTarget,k)).attr2("name"))?m=b:h.attr2("name",m):(h=e('<iframe name="'+m+'" src="'+f.iframeSrc+'" />',k)).css({position:"absolute",top:"-1000px",left:"-1000px"}),v=h[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{v.contentWindow.document.execCommand&&v.contentWindow.document.execCommand("Stop")}catch(e){}h.attr("src",f.iframeSrc),x.error=r,f.error&&f.error.call(f.context,x,r,t),d&&e.event.trigger("ajaxError",[x,f,r]),f.complete&&f.complete.call(f.context,x,r)}},(d=f.global)&&0==e.active++&&e.event.trigger("ajaxStart"),d&&e.event.trigger("ajaxSend",[x,f]),f.beforeSend&&!1===f.beforeSend.c
15098all(f.context,x,f))return f.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;(y=w.clk)&&(b=y.name)&&!y.disabled&&(f.extraData=f.extraData||{},f.extraData[b]=y.value,"image"===y.type&&(f.extraData[b+".x"]=w.clk_x,f.extraData[b+".y"]=w.clk_y));var A=1,L=2,F=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&F&&(f.extraData=f.extraData||{},f.extraData[E]=F),f.forceSync?i():setTimeout(i,10);var M,O,X,C=50,q=e.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},_=e.parseJSON||function(e){return window.eval("("+e+")")},N=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i=("xml"===r||!r)&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&(("json"===r||!r)&&n.indexOf("json")>=0?o=_(o):("script"===r||!r)&&n.indexOf("javascript")>=0&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var l,f,d,p=this;"function"==typeof t?t={success:t}
15098:"string"==typeof t||!1===t&&arguments.length>0?(t={url:t,data:r,dataType:n},"function"==typeof s&&(t.success=s)):void 0===t&&(t={}),l=t.method||t.type||this.attr2("method"),(d=(d="string"==typeof(f=t.url||this.attr2("action"))?e.trim(f):"")||window.location.href||"")&&(d=(d.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:d,success:e.ajaxSettings.success,type:l||e.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&!1===t.beforeSerialize(this,t))return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var h=t.traditional;void 0===h&&(h=e.ajaxSettings.traditional);var v,g=[],x=this.formToArray(t.semantic,g,t.filtering);if(t.data){var y=e.isFunction(t.data)?t.data(x):t.data;t.extraData=y,v=e.param(y,h)}if(t.beforeSubmit&&!1===t.beforeSubmit(x,this,t))return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[x,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var b=e.param(x,h);v&&(b=b?b+"&"+v:v),"GET"===t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+b,t.data=null):t.data=b;var T=[];
15098if(t.resetForm&&T.push(function(){p.resetForm()}),t.clearForm&&T.push(function(){p.clearForm(t.includeHidden)}),!t.dataType&&t.target){var j=t.success||function(){};T.push(function(r,a,n){var i=arguments,o=t.replaceTarget?"replaceWith":"html";e(t.target)[o](r).each(function(){j.apply(this,i)})})}else t.success&&(e.isArray(t.success)?e.merge(T,t.success):T.push(t.success));if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=T.length;i<o;i++)T[i].apply(n,[e,r,a||p,p])},t.error){var w=t.error;t.error=function(e,r,a){var n=t.context||this;w.apply(n,[e,r,a,p])}}if(t.complete){var S=t.complete;t.complete=function(e,r){var a=t.context||this;S.apply(a,[e,r,p])}}var k=e("input[type=file]:enabled",this).filter(function(){return""!==e(this).val()}).length>0,D="multipart/form-data",A=p.attr("enctype")===D||p.attr("encoding")===D,L=i.fileapi&&i.formdata;a("fileAPI :"+L);var F,E=(k||A)&&!L;!1!==t.iframe&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){F=c(x)}):F=c(x):F=(k||A)&&L?function(r){for(var a=new FormData,n=0;n<r.length;n++)a.append(r[n].name,r[n].value);if(t.extraData){var i=u(t.extraData);for(n=0;n<i.length;n++)i[n]&&a.append(i[n][0],i[n][1])}t.data=null;var o=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:l||"POST"});t.uploadProgress&&(o.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(a/n*100)),t.uploadProgress(e,a,n,r)},!1),r}),o.data=null;var s=o.beforeSend;return o.beforeSend=function(e,r){t.formData?r.data=t.formData:r.data=a,s&&s.call(this,e,r)},e.ajax(o)}(x):e.ajax(t),p.removeData("jqxhr").data("jqxhr",F);for(var M=0;M<g.length;M++)g[M]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n,i,o,s){if(("string"==typeof n||!1===n&&arguments.length>0)&&(n={url:n,data:i,dataType:o},"function"==typeof s&&(n.success=s)),n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var u={s:this.selector,c:this.context};return!e.isReady&&u.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(u.s,u.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().on("submit.form-plugin",n,t).on("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r,a){var n=[];if(0===this.length)return n;var o,s=this[0],u=this.attr("id"),c=t||void 0===s.elements?s.getElementsByTagName("*"):s.elements;if(c&&(c=e.makeArray(c)),u&&(t||/(Edge|Trident)\//.test(navigator.userAgent))&&(o=e(':input[form="'+u+'"]').get()).length&&(c=(c||[]).concat(o)),!c||!c.length)return n;e.isFunction(a)&&(c=e.map(c,a));var l,f,d,p,m,h,v;for(l=0,h=c.length;l<h;l++)if(m=c[l],(d=m.name)&&!m.disabled)if(t&&s.clk&&"image"===m.type)s.clk===m&&(n.push({name:d,value:e(m).val(),type:m.type}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}));else if((p=e.fieldValue(m,!0))&&p.constructor===Array)for(r&&r.push(m),f=0,v=p.length;f<v;f++)n.push({name:d,value:p[f]});else if(i.fileapi&&"file"===m.type){r&&r.push(m);var g=m.files;if(g.length)for(f=0;f<g.length;f++)n.push({name:d,value:g[f],type:m.type});else n.push({name:d,value:"",type:m.type})}else null!==p&&void 0!==p&&(r&&r.push(m),n.push({name:d,value:p,type:m.type,required:m.required}));if(!t&&s.clk){var x=e(s.clk),y=x[0];(d=y.name)&&!y.disabled&&"image"===y.type&&(n.push({name:d,value:x.val()}),n.push({name:d+".x",value:s.clk_x},{name:d+".y",value:s.clk_y}))}return n},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor===Array)for(var i=0,o=n.length;i<o;i++)r.push({name:a,value:n[i]});else null!==n&&void 0!==n&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;a<n;a++){var i=this[a],o=e.fieldValue(i,t);null===o||void 0===o||o.constructor===Array&&!o.length||(o.constructor===Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,i=t.type,o=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"===i||"button"===i||("checkbox"===i||"radio"===i)&&!t.checked||("submit"===i||"image"===i)&&t.form&&t.form.clk!==t||"select"===o&&-1===t.selectedIndex))return null;if("select"===o){var s=t.selectedIndex;if(s<0)return null;for(var u=[],c=t.options,l="select-one"===i,f=l?s+1:c.length,d=l?s:0;d<f;d++){var p=c[d];if(p.selected&&!p.disabled){var m=p.value;if(m||(m=p.attributes&&p.attributes.value&&!p.attributes.value.specified?p.text:p.value),l)return m;u.push(m)}}return u}return e(t).val().replace(n,"\r\n")},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"===n?this.value="":"checkbox"===a||"radio"===a?this.checked=!1:"select"===n?this.selectedIndex=-1:"file"===a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(!0===t&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")}
15098)},e.fn.resetForm=function(){return this.each(function(){var t=e(this),r=this.tagName.toLowerCase();switch(r){case"input":this.checked=this.defaultChecked;case"textarea":return this.value=this.defaultValue,!0;case"option":case"optgroup":var a=t.parents("select");return a.length&&a[0].multiple?"option"===r?this.selected=this.defaultSelected:t.find("option").resetForm():a.resetForm(),!0;case"select":return t.find("option").each(function(e){if(this.selected=this.defaultSelected,this.defaultSelected&&!t[0].multiple)return t[0].selectedIndex=e,!1}),!0;case"label":var n=e(t.attr("for")),i=t.find("input,select,textarea");return n[0]&&i.unshift(n[0]),i.resetForm(),!0;case"form":return("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset(),!0;default:return t.find("form,input,label,select,textarea").resetForm(),!0}})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"===r||"radio"===r)this.checked=t;else if("option"===this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"===a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1}); 15099//# sourceMappingURL=jquery.form.min.js.map 15100 15101/*! 15102 * jQuery blockUI plugin 15103 * Version 2.70.0-2014.11.23 15104 * Requires jQuery v1.7 or later 15105 * 15106 * Examples at: http://malsup.com/jquery/block/ 15107 * Copyright (c) 2007-2013 M. Alsup 15108 * Dual licensed under the MIT and GPL licenses: 15109 * http://www.opensource.org/licenses/mit-license.php 15110 * http://www.gnu.org/licenses/gpl.html 15111 * 15112 * Thanks to Amir-Hossein Sobhi for some excellent contributions! 15113 */ 15114 15115;(function() { 15116/*jshint eqeqeq:false curly:false latedef:false */ 15117"use strict"; 15118 15119 function setup($) { 15120 $.fn._fadeIn = $.fn.fadeIn; 15121 15122 var noOp = $.noop || function() {}; 15123 15124 // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle 15125 // confusing userAgent strings on Vista) 15126 var msie = /MSIE/.test(navigator.userAgent); 15127 var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent); 15128 var mode = document.documentMode || 0; 15129 var setExpr = $.isFunction( document.createElement('div').style.setExpression ); 15130 15131 // global $ methods for blocking/unblocking the entire page 15132 $.blockUI = function(opts) { install(window, opts); }; 15133 $.unblockUI = function(opts) { remove(window, opts); }; 15134 15135 // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) 15136 $.growlUI = function(title, message, timeout, onClose) { 15137 var $m = $('<div class="growlUI"></div>'); 15138 if (title) $m.append('<h1>'+title+'</h1>'); 15139 if (message) $m.append('<h2>'+message+'</h2>'); 15140 if (timeout === undefined) timeout = 3000; 15141 15142 // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications 15143 var callBlock = function(opts) { 15144 opts = opts || {}; 15145 15146 $.blockUI({ 15147 message: $m, 15148 fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700, 15149 fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000, 15150 timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout, 15151 centerY: false, 15152 showOverlay: false, 15153 onUnblock: onClose, 15154 css: $.blockUI.defaults.growlCSS 15155 }); 15156 }; 15157 15158 callBlock(); 15159 var nonmousedOpacity = $m.css('opacity'); 15160 $m.mouseover(function() { 15161 callBlock({ 15162 fadeIn: 0, 15163 timeout: 30000 15164 }); 15165 15166 var displayBlock = $('.blockMsg'); 15167 displayBlock.stop(); // cancel fadeout if it has started 15168 displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency 15169 }).mouseout(function() { 15170 $('.blockMsg').fadeOut(1000); 15171 }); 15172 // End konapun additions 15173 }; 15174 15175 // plugin method for blocking element content 15176 $.fn.block = function(opts) { 15177 if ( this[0] === window ) { 15178 $.blockUI( opts ); 15179 return this; 15180 } 15181 var fullOpts = $.extend({}, $.blockUI.defaults, opts || {}); 15182 this.each(function() { 15183 var $el = $(this); 15184 if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked')) 15185 return; 15186 $el.unblock({ fadeOut: 0 }); 15187 }); 15188 15189 return this.each(function() { 15190 if ($.css(this,'position') == 'static') { 15191 this.style.position = 'relative'; 15192 $(this).data('blockUI.static', true); 15193 } 15194 this.style.zoom = 1; // force 'hasLayout' in ie 15195 install(this, opts); 15196 }); 15197 }; 15198 15199 // plugin method for unblocking element content 15200 $.fn.unblock = function(opts) { 15201 if ( this[0] === window ) { 15202 $.unblockUI( opts ); 15203 return this; 15204 } 15205 return this.each(function() { 15206 remove(this, opts); 15207 }); 15208 }; 15209 15210 $.blockUI.version = 2.70; // 2nd generation blocking at no extra cost! 15211 15212 // override these in your code to change the default behavior and style 15213 $.blockUI.defaults = { 15214 // message displayed when blocking (use null for no message) 15215 message: '<h1>Please wait...</h1>', 15216 15217 title: null, // title string; only used when theme == true 15218 draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) 15219 15220 theme: false, // set to true to use with jQuery UI themes 15221 15222 // styles for the message when blocking; if you wish to disable 15223 // these and use an external stylesheet then do this in your code: 15224 // $.blockUI.defaults.css = {}; 15225 css: { 15226 padding: 0, 15227 margin: 0, 15228 width: '30%', 15229 top: '40%', 15230 left: '35%', 15231 textAlign: 'center', 15232 color: '#000', 15233 border: '3px solid #aaa', 15234 backgroundColor:'#fff', 15235 cursor: 'wait' 15236 }, 15237 15238 // minimal style set used when themes are used 15239 themedCSS: { 15240 width: '30%', 15241 top: '40%', 15242 left: '35%' 15243 }, 15244 15245 // styles for the overlay 15246 overlayCSS: { 15247 backgroundColor: '#000', 15248 opacity: 0.6, 15249 cursor: 'wait' 15250 }, 15251 15252 // style to replace wait cursor before unblocking to correct issue 15253 // of lingering wait cursor 15254 cursorReset: 'default', 15255 15256 // styles applied when using $.growlUI 15257 growlCSS: { 15258 width: '350px', 15259 top: '10px', 15260 left: '', 15261 right: '10px', 15262 border: 'none', 15263 padding: '5px', 15264 opacity: 0.6, 15265 cursor: 'default', 15266 color: '#fff', 15267 backgroundColor: '#000', 15268 '-webkit-border-radius':'10px', 15269 '-moz-border-radius': '10px', 15270 'border-radius': '10px' 15271 }, 15272 15273 // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w 15274 // (hat tip to Jorge H. N. de Vasconcelos) 15275 /*jshint scripturl:true */ 15276 iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', 15277 15278 // force usage of iframe in non-IE browsers (handy for blocking applets) 15279 forceIframe: false, 15280 15281 // z-index for the blocking overlay 15282 baseZ: 1000, 15283 15284 // set these to true to have the message automatically centered 15285 centerX: true, // <-- only effects element blocking (page block controlled via css above) 15286 centerY: true, 15287 15288 // allow body element to be stetched in ie6; this makes blocking look better 15289 // on "short" pages. disable if you wish to prevent changes to the body height 15290 allowBodyStretch: true, 15291 15292 // enable if you want key and mouse events to be disabled for content that is blocked 15293 bindEvents: true, 15294 15295 // be default blockUI will supress tab navigation from leaving blocking content 15296 // (if bindEvents is true) 15297 constrainTabKey: true, 15298 15299 // fadeIn time in millis; set to 0 to disable fadeIn on block 15300 fadeIn: 200, 15301 15302 // fadeOut time in millis; set to 0 to disable fadeOut on unblock 15303 fadeOut: 400, 15304 15305 // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock 15306 timeout: 0, 15307 15308 // disable if you don't want to show the overlay 15309 showOverlay: true, 15310 15311 // if true, focus will be placed in the first available input field when 15312 // page blocking 15313 focusInput: true, 15314 15315 // elements that can receive focus 15316 focusableElements: ':input:enabled:visible', 15317 15318 // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) 15319 // no longer needed in 2012 15320 // applyPlatformOpacityRules: true, 15321 15322 // callback method invoked when fadeIn has completed and blocking message is visible 15323 onBlock: null, 15324 15325 // callback method invoked when unblocking has completed; the callback is 15326 // passed the element that has been unblocked (which is the window object for page 15327 // blocks) and the options that were passed to the unblock call: 15328 // onUnblock(element, options) 15329 onUnblock: null, 15330 15331 // callback method invoked when the overlay area is clicked. 15332 // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used. 15333 onOverlayClick: null, 15334 15335 // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
vendor: 11,306 bytes, lines 15336-15673
15336 quirksmodeOffsetHack: 4, 15337 15338 // class name of the message block 15339 blockMsgClass: 'blockMsg', 15340 15341 // if it is already blocked, then ignore it (don't unblock and reblock) 15342 ignoreIfBlocked: false 15343 }; 15344 15345 // private data and functions follow... 15346 15347 var pageBlock = null; 15348 var pageBlockEls = []; 15349 15350 function install(el, opts) { 15351 var css, themedCSS; 15352 var full = (el == window); 15353 var msg = (opts && opts.message !== undefined ? opts.message : undefined); 15354 opts = $.extend({}, $.blockUI.defaults, opts || {}); 15355 15356 if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked')) 15357 return; 15358 15359 opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); 15360 css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); 15361 if (opts.onOverlayClick) 15362 opts.overlayCSS.cursor = 'pointer'; 15363 15364 themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); 15365 msg = msg === undefined ? opts.message : msg; 15366 15367 // remove the current block (if there is one) 15368 if (full && pageBlock) 15369 remove(window, {fadeOut:0}); 15370 15371 // if an existing element is being used as the blocking content then we capture 15372 // its current place in the DOM (and current display style) so we can restore 15373 // it when we unblock 15374 if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { 15375 var node = msg.jquery ? msg[0] : msg; 15376 var data = {}; 15377 $(el).data('blockUI.history', data); 15378 data.el = node; 15379 data.parent = node.parentNode; 15380 data.display = node.style.display; 15381 data.position = node.style.position; 15382 if (data.parent) 15383 data.parent.removeChild(node); 15384 } 15385 15386 $(el).data('blockUI.onUnblock', opts.onUnblock); 15387 var z = opts.baseZ; 15388 15389 // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; 15390 // layer1 is the iframe layer which is used to supress bleed through of underlying content 15391 // layer2 is the overlay layer which has opacity and a wait cursor (by default) 15392 // layer3 is the message content that is displayed while blocking 15393 var lyr1, lyr2, lyr3, s; 15394 if (msie || opts.forceIframe) 15395 lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>'); 15396 else 15397 lyr1 = $('<div class="blockUI" style="display:none"></div>'); 15398 15399 if (opts.theme) 15400 lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>'); 15401 else 15402 lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'); 15403 15404 if (opts.theme && full) { 15405 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">'; 15406 if ( opts.title ) { 15407 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>'; 15408 } 15409 s += '<div class="ui-widget-content ui-dialog-content"></div>'; 15410 s += '</div>'; 15411 } 15412 else if (opts.theme) { 15413 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">'; 15414 if ( opts.title ) { 15415 s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>'; 15416 } 15417 s += '<div class="ui-widget-content ui-dialog-content"></div>'; 15418 s += '</div>'; 15419 } 15420 else if (full) { 15421 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>'; 15422 } 15423 else { 15424 s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>'; 15425 } 15426 lyr3 = $(s); 15427 15428 // if we have a message, style it 15429 if (msg) { 15430 if (opts.theme) { 15431 lyr3.css(themedCSS); 15432 lyr3.addClass('ui-widget-content'); 15433 } 15434 else 15435 lyr3.css(css); 15436 } 15437 15438 // style the overlay 15439 if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/) 15440 lyr2.css(opts.overlayCSS); 15441 lyr2.css('position', full ? 'fixed' : 'absolute'); 15442 15443 // make iframe layer transparent in IE 15444 if (msie || opts.forceIframe) 15445 lyr1.css('opacity',0.0); 15446 15447 //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); 15448 var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); 15449 $.each(layers, function() { 15450 this.appendTo($par); 15451 }); 15452 15453 if (opts.theme && opts.draggable && $.fn.draggable) { 15454 lyr3.draggable({ 15455 handle: '.ui-dialog-titlebar', 15456 cancel: 'li' 15457 }); 15458 } 15459 15460 // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) 15461 var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0); 15462 if (ie6 || expr) { 15463 // give body 100% height 15464 if (full && opts.allowBodyStretch && $.support.boxModel) 15465 $('html,body').css('height','100%'); 15466 15467 // fix ie6 issue when blocked element has a border width 15468 if ((ie6 || !$.support.boxModel) && !full) { 15469 var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); 15470 var fixT = t ? '(0 - '+t+')' : 0; 15471 var fixL = l ? '(0 - '+l+')' : 0; 15472 } 15473 15474 // simulate fixed position 15475 $.each(layers, function(i,o) { 15476 var s = o[0].style; 15477 s.position = 'absolute'; 15478 if (i < 2) { 15479 if (full) 15480 s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"'); 15481 else 15482 s.setExpression('height','this.parentNode.offsetHeight + "px"'); 15483 if (full) 15484 s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'); 15485 else 15486 s.setExpression('width','this.parentNode.offsetWidth + "px"'); 15487 if (fixL) s.setExpression('left', fixL); 15488 if (fixT) s.setExpression('top', fixT); 15489 } 15490 else if (opts.centerY) { 15491 if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); 15492 s.marginTop = 0; 15493 } 15494 else if (!opts.centerY && full) { 15495 var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0; 15496 var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; 15497 s.setExpression('top',expression); 15498 } 15499 }); 15500 } 15501 15502 // show the message 15503 if (msg) { 15504 if (opts.theme) 15505 lyr3.find('.ui-widget-content').append(msg); 15506 else 15507 lyr3.append(msg); 15508 if (msg.jquery || msg.nodeType) 15509 $(msg).show(); 15510 } 15511 15512 if ((msie || opts.forceIframe) && opts.showOverlay) 15513 lyr1.show(); // opacity is zero 15514 if (opts.fadeIn) { 15515 var cb = opts.onBlock ? opts.onBlock : noOp; 15516 var cb1 = (opts.showOverlay && !msg) ? cb : noOp; 15517 var cb2 = msg ? cb : noOp; 15518 if (opts.showOverlay) 15519 lyr2._fadeIn(opts.fadeIn, cb1); 15520 if (msg) 15521 lyr3._fadeIn(opts.fadeIn, cb2); 15522 } 15523 else { 15524 if (opts.showOverlay) 15525 lyr2.show(); 15526 if (msg) 15527 lyr3.show(); 15528 if (opts.onBlock) 15529 opts.onBlock.bind(lyr3)(); 15530 } 15531 15532 // bind key and mouse events 15533 bind(1, el, opts); 15534 15535 if (full) { 15536 pageBlock = lyr3[0]; 15537 pageBlockEls = $(opts.focusableElements,pageBlock); 15538 if (opts.focusInput) 15539 setTimeout(focus, 20); 15540 } 15541 else 15542 center(lyr3[0], opts.centerX, opts.centerY); 15543 15544 if (opts.timeout) { 15545 // auto-unblock 15546 var to = setTimeout(function() { 15547 if (full) 15548 $.unblockUI(opts); 15549 else 15550 $(el).unblock(opts); 15551 }, opts.timeout); 15552 $(el).data('blockUI.timeout', to); 15553 } 15554 } 15555 15556 // remove the block 15557 function remove(el, opts) { 15558 var count; 15559 var full = (el == window); 15560 var $el = $(el); 15561 var data = $el.data('blockUI.history'); 15562 var to = $el.data('blockUI.timeout'); 15563 if (to) { 15564 clearTimeout(to); 15565 $el.removeData('blockUI.timeout'); 15566 } 15567 opts = $.extend({}, $.blockUI.defaults, opts || {}); 15568 bind(0, el, opts); // unbind events 15569 15570 if (opts.onUnblock === null) { 15571 opts.onUnblock = $el.data('blockUI.onUnblock'); 15572 $el.removeData('blockUI.onUnblock'); 15573 } 15574 15575 var els; 15576 if (full) // crazy selector to handle odd field errors in ie6/7 15577 els = $('body').children().filter('.blockUI').add('body > .blockUI'); 15578 else 15579 els = $el.find('>.blockUI'); 15580 15581 // fix cursor issue 15582 if ( opts.cursorReset ) { 15583 if ( els.length > 1 ) 15584 els[1].style.cursor = opts.cursorReset; 15585 if ( els.length > 2 ) 15586 els[2].style.cursor = opts.cursorReset; 15587 } 15588 15589 if (full) 15590 pageBlock = pageBlockEls = null; 15591 15592 if (opts.fadeOut) { 15593 count = els.length; 15594 els.stop().fadeOut(opts.fadeOut, function() { 15595 if ( --count === 0) 15596 reset(els,data,opts,el); 15597 }); 15598 } 15599 else 15600 reset(els, data, opts, el); 15601 } 15602 15603 // move blocking element back into the DOM where it started 15604 function reset(els,data,opts,el) { 15605 var $el = $(el); 15606 if ( $el.data('blockUI.isBlocked') ) 15607 return; 15608 15609 els.each(function(i,o) { 15610 // remove via DOM calls so we don't lose event handlers 15611 if (this.parentNode) 15612 this.parentNode.removeChild(this); 15613 }); 15614 15615 if (data && data.el) { 15616 data.el.style.display = data.display; 15617 data.el.style.position = data.position; 15618 data.el.style.cursor = 'default'; // #59 15619 if (data.parent) 15620 data.parent.appendChild(data.el); 15621 $el.removeData('blockUI.history'); 15622 } 15623 15624 if ($el.data('blockUI.static')) { 15625 $el.css('position', 'static'); // #22 15626 } 15627 15628 if (typeof opts.onUnblock == 'function') 15629 opts.onUnblock(el,opts); 15630 15631 // fix issue in Safari 6 where block artifacts remain until reflow 15632 var body = $(document.body), w = body.width(), cssW = body[0].style.width; 15633 body.width(w-1).width(w); 15634 body[0].style.width = cssW; 15635 } 15636 15637 // bind/unbind the handler 15638 function bind(b, el, opts) { 15639 var full = el == window, $el = $(el); 15640 15641 // don't bother unbinding if there is nothing to unbind 15642 if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) 15643 return; 15644 15645 $el.data('blockUI.isBlocked', b); 15646 15647 // don't bind events when overlay is not in use or if bindEvents is false 15648 if (!full || !opts.bindEvents || (b && !opts.showOverlay)) 15649 return; 15650 15651 // bind anchors and inputs for mouse and key events 15652 var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove'; 15653 if (b) 15654 $(document).bind(events, opts, handler); 15655 else 15656 $(document).unbind(events, handler); 15657 15658 // former impl... 15659 // var $e = $('a,:input'); 15660 // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); 15661 } 15662 15663 // event handler to suppress keyboard/mouse events when blocking 15664 function handler(e) { 15665 // allow tab navigation (conditionally) 15666 if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) { 15667 if (pageBlock && e.data.constrainTabKey) { 15668 var els = pageBlockEls; 15669 var fwd = !e.shiftKey && e.target === els[els.length-1]; 15670 var back = e.shiftKey && e.target === els[0]; 15671 if (fwd || back) { 15672 setTimeout(function(){focus(back);},10); 15673 return false;
15674 } 15675 } 15676 } 15677 var opts = e.data; 15678 var target = $(e.target); 15679 if (target.hasClass('blockOverlay') && opts.onOverlayClick) 15680 opts.onOverlayClick(e); 15681 15682 // allow events within the message content 15683 if (target.parents('div.' + opts.blockMsgClass).length > 0) 15684 return true; 15685 15686 // allow events for content that is not being blocked 15687 return target.parents().children().filter('div.blockUI').length === 0; 15688 } 15689 15690 function focus(back) { 15691 if (!pageBlockEls) 15692 return; 15693 var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; 15694 if (e) 15695 e.focus(); 15696 } 15697 15698 function center(el, x, y) { 15699 var p = el.parentNode, s = el.style; 15700 var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); 15701 var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); 15702 if (x) s.left = l > 0 ? (l+'px') : '0'; 15703 if (y) s.top = t > 0 ? (t+'px') : '0'; 15704 } 15705 15706 function sz(el, p) { 15707 return parseInt($.css(el,p),10)||0; 15708 } 15709 15710 } 15711 15712 15713 /*global define:true */ 15714 if (typeof define === 'function' && define.amd) { 15715 // AMD. Register as an anonymous module. 15716 define(['jquery'], setup); 15717 } else if (typeof exports === 'object') { 15718 // Node/CommonJS 15719 setup(require('jquery')); 15720 } else { 15721 // Browser globals 15722 setup(jQuery); 15723 } 15724 15725})(); 15726 15727/*! 15728 * Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker) 15729 * 15730 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) 15731 */ 15732 15733!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(c,d){return function(){return d!==b&&a.fn.datepicker.deprecated(d),this[c].apply(this,arguments)}}function g(a){return a&&!isNaN(a.getTime())}function h(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function i(b){var c={};if(q[b]||(b=b.split("-")[0],q[b])){var d=q[b];return a.each(p,function(a,b){b in d&&(c[b]=d[b])}),c}}var j=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;c<d;c++)if(0<=this[c].valueOf()-b&&this[c].valueOf()-b<864e5)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new j;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),k=function(b,c){a.data(b,"datepicker",this),this._events=[],this._secondaryEvents=[],this._process_options(c),this.dates=new j,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInput=this.element.is("input"),this.inputField=this.isInput?this.element:this.element.find("input"),this.component=!!this.element.hasClass("date")&&this.element.find(".add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn"),this.component&&0===this.component.length&&(this.component=!1),this.isInline=!this.component&&this.element.is("div"),this.picker=a(r.template),this._check_template(this.o.templates.leftArrow)&&this.picker.find(".prev").html(this.o.templates.leftArrow),this._check_template(this.o.templates.rightArrow)&&this.picker.find(".next").html(this.o.templates.rightArrow),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.o.calendarWeeks&&this.picker.find(".datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear").attr("colspan",function(a,b){return Number(b)+1}
vendor: 13,629 bytes, line 15733
15733),this._process_options({startDate:this._o.startDate,endDate:this._o.endDate,daysOfWeekDisabled:this.o.daysOfWeekDisabled,daysOfWeekHighlighted:this.o.daysOfWeekHighlighted,datesDisabled:this.o.datesDisabled}),this._allow_update=!1,this.setViewMode(this.o.startView),this._allow_update=!0,this.fillDow(),this.fillMonths(),this.update(),this.isInline&&this.show()};k.prototype={constructor:k,_resolveViewName:function(b){return a.each(r.viewModes,function(c,d){if(b===c||-1!==a.inArray(b,d.names))return b=c,!1}),b},_resolveDaysOfWeek:function(b){return a.isArray(b)||(b=b.split(/[,\s]*/)),a.map(b,Number)},_check_template:function(c){try{if(c===b||""===c)return!1;if((c.match(/[<>]/g)||[]).length<=0)return!0;return a(c).length>0}catch(a){return!1}},_process_options:function(b){this._o=a.extend({},this._o,b);var e=this.o=a.extend({},this._o),f=e.language;q[f]||(f=f.split("-")[0],q[f]||(f=o.language)),e.language=f,e.startView=this._resolveViewName(e.startView),e.minViewMode=this._resolveViewName(e.minViewMode),e.maxViewMode=this._resolveViewName(e.maxViewMode),e.startView=Math.max(this.o.minViewMode,Math.min(this.o.maxViewMode,e.startView)),!0!==e.multidate&&(e.multidate=Number(e.multidate)||!1,!1!==e.multidate&&(e.multidate=Math.max(0,e.multidate))),e.multidateSeparator=String(e.multidateSeparator),e.weekStart%=7,e.weekEnd=(e.weekStart+6)%7;var g=r.parseFormat(e.format);e.startDate!==-1/0&&(e.startDate?e.startDate instanceof Date?e.startDate=this._local_to_utc(this._zero_time(e.startDate)):e.startDate=r.parseDate(e.startDate,g,e.language,e.assumeNearbyYear):e.startDate=-1/0),e.endDate!==1/0&&(e.endDate?e.endDate instanceof Date?e.endDate=this._local_to_utc(this._zero_time(e.endDate)):e.endDate=r.parseDate(e.endDate,g,e.language,e.assumeNearbyYear):e.endDate=1/0),e.daysOfWeekDisabled=this._resolveDaysOfWeek(e.daysOfWeekDisabled||[]),e.daysOfWeekHighlighted=this._resolveDaysOfWeek(e.daysOfWeekHighlighted||[]),e.datesDisabled=e.datesDisabled||[],a.isArray(e.datesDisabled)||(e.datesDisabled=e.datesDisabled.split(",")),e.datesDisabled=a.map(e.datesDisabled,function(a){return r.parseDate(a,g,e.language,e.assumeNearbyYear)});var h=String(e.orientation).toLowerCase().split(/\s+/g),i=e.orientation.toLowerCase();if(h=a.grep(h,function(a){return/^auto|left|right|top|bottom$/.test(a)}),e.orientation={x:"auto",y:"auto"},i&&"auto"!==i)if(1===h.length)switch(h[0]){case"top":case"bottom":e.orientation.y=h[0];break;case"left":case"right":e.orientation.x=h[0]}else i=a.grep(h,function(a){return/^left|right$/.test(a)}),e.orientation.x=i[0]||"auto",i=a.grep(h,function(a){return/^top|bottom$/.test(a)}),e.orientation.y=i[0]||"auto";else;if(e.defaultViewDate instanceof Date||"string"==typeof e.defaultViewDate)e.defaultViewDate=r.parseDate(e.defaultViewDate,g,e.language,e.assumeNearbyYear);else if(e.defaultViewDate){var j=e.defaultViewDate.year||(new Date).getFullYear(),k=e.defaultViewDate.month||0,l=e.defaultViewDate.day||1;e.defaultViewDate=c(j,k,l)}else e.defaultViewDate=d()},_applyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(d=b,e=a[f][1]):3===a[f].length&&(d=a[f][1],e=a[f][2]),c.on(e,d)},_unapplyEvents:function(a){for(var c,d,e,f=0;f<a.length;f++)c=a[f][0],2===a[f].length?(e=b,d=a[f][1]):3===a[f].length&&(e=a[f][1],d=a[f][2]),c.off(d,e)},_buildEvents:function(){var b={keyup:a.proxy(function(b){-1===a.inArray(b.keyCode,[27,37,39,38,40,32,13,9])&&this.update()},this),keydown:a.proxy(this.keydown,this),paste:a.proxy(this.paste,this)};!0===this.o.showOnFocus&&(b.focus=a.proxy(this.show,this)),this.isInput?this._events=[[this.element,b]]:this.component&&this.inputField.length?this._events=[[this.inputField,b],[this.component,{click:a.proxy(this.show,this)}]]:this._events=[[this.element,{click:a.proxy(this.show,this),keydown:a.proxy(this.keydown,this)}]],this._events.push([this.element,"*",{blur:a.proxy(function(a){this._focused_from=a.target},this)}],[this.element,{blur:a.proxy(function(a){this._focused_from=a.target},this)}]),this.o.immediateUpdates&&this._events.push([this.element,{"changeYear changeMonth":a.proxy(function(a){this.update(a.date)},this)}]),this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[this.picker,".prev, .next",{click:a.proxy(this.navArrowsClick,this)}],[this.picker,".day:not(.disabled)",{click:a.proxy(this.dayCellClick,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{"mousedown touchstart":a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).length||this.picker.is(a.target)||this.picker.find(a.target).length||this.isInline||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.dates.get(-1),e=this._utc_to_local(d);this.element.trigger({type:b,date:e,viewMode:this.viewMode,dates:a.map(this.dates,this._utc_to_local),format:a.proxy(function(a,b){0===arguments.length?(a=this.dates.length-1,b=this.o.format):"string"==typeof a&&(b=a,a=this.dates.length-1),b=b||this.o.format;var c=this.dates.get(a);return r.formatDate(c,b,this.o.language)},this)})},show:function(){if(!(this.inputField.is(":disabled")||this.inputField.prop("readonly")&&!1===this.o.enableOnReadonly))return this.isInline||this.picker.appendTo(this.o.container),this.place(),this.picker.show(),this._attachSecondaryEvents(),this._trigger("show"),(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&this.o.disableTouchKeyboard&&a(this.element).blur(),this},hide:function(){return this.isInline||!this.picker.is(":visible")?this:(this.focusDate=null,this.picker.hide().detach(),this._detachSecondaryEvents(),this.setViewMode(this.o.startView),this.o.forceParse&&this.inputField.val()&&this.setValue(),this._trigger("hide"),this)},destroy:function(){return this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date,this},paste:function(b){var c;if(b.originalEvent.clipboardData&&b.originalEvent.clipboardData.types&&-1!==a.inArray("text/plain",b.originalEvent.clipboardData.types))c=b.originalEvent.clipboardData.getData("text/plain");else{if(!window.clipboardData)return;c=window.clipboardData.getData("Text")}this.setDate(c),this.update(),b.preventDefault()},_utc_to_local:function(a){if(!a)return a;var b=new Date(a.getTime()+6e4*a.getTimezoneOffset());return b.getTimezoneOffset()!==a.getTimezoneOffset()&&(b=new Date(a.getTime()+6e4*b.getTimezoneOffset())),b},_local_to_utc:function(a){return a&&new Date(a.getTime()-6e4*a.getTimezoneOffset())},_zero_time:function(a){return a&&new Date(a.getFullYear(),a.getMonth(),a.getDate())},_zero_utc_time:function(a){return a&&c(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate())},getDates:function(){return a.map(this.dates,this._utc_to_local)},getUTCDates:function(){return a.map(this.dates,function(a){return new Date(a)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){var a=this.dates.get(-1);return a!==b?new Date(a):null},clearDates:function(){this.inputField.val(""),this.update(),this._trigger("changeDate"),this.o.autoclose&&this.hide()},setDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.update.apply(this,b),this._trigger("changeDate"),this.setValue(),this},setUTCDates:function(){var b=a.isArray(arguments[0])?arguments[0]:arguments;return this.setDates.apply(this,a.map(b,this._utc_to_local)),this},setDate:f("setDates"),setUTCDate:f("setUTCDates"),remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead"),setValue:function(){var a=this.getFormattedDate();return this.inputField.val(a),this},getFormattedDate:function(c){c===b&&(c=this.o.format);var d=this.o.language;return a.map(this.dates,function(a){return r.formatDate(a,c,d)}).join(this.o.multidateSeparator)},getStartDate:function(){return this.o.startDate},setStartDate:function(a){return this._process_options({startDate:a}),this.update(),this.updateNavArrows(),this},getEndDate:function(){return this.o.endDate},setEndDate:function(a){return this._process_options({endDate:a}),this.update(),this.updateNavArrows(),this},setDaysOfWeekDisabled:function(a){return this._process_options({daysOfWeekDisabled:a}),this.update(),this},setDaysOfWeekHighlighted:function(a){return this._process_options({daysOfWeekHighlighted:a}),this.update(),this},setDatesDisabled:function(a){return this._process_options({datesDisabled:a}),this.update(),this},place:function(){if(this.isInline)return this;var b=this.picker.outerWidth(),c=this.picker.outerHeight(),d=a(this.o.container),e=d.width(),f="body"===this.o.container?a(document).scrollTop():d.scrollTop(),g=d.offset(),h=[0];this.element.parents().each(function(){var b=a(this).css("z-index");"auto"!==b&&0!==Number(b)&&h.push(Number(b))});var i=Math.max.apply(Math,h)+this.o.zIndexOffset,j=this.component?this.component.parent().offset():this.element.offset(),k=this.component?this.component.outerHeight(!0):this.element.outerHeight(!1),l=this.component?this.component.outerWidth(!0):this.element.outerWidth(!1),m=j.left-g.left,n=j.top-g.top;"body"!==this.o.container&&(n+=f),this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom datepicker-orient-right datepicker-orient-left"),"auto"!==this.o.orientation.x?(this.picker.addClass("datepicker-orient-"+this.o.orientation.x),"right"===this.o.orientation.x&&(m-=b-l)):j.left<0?(this.picker.addClass("datepicker-orient-left"),m-=j.left-10):m+b>e?(this.picker.addClass("datepicker-orient-right"),m+=l-b):this.o.rtl?this.picker.addClass("datepicker-orient-right"):this.picker.addClass("datepicker-orient-left");var o,p=this.o.orientation.y;if("auto"===p&&(o=-f+n-c,p=o<0?"bottom":"top"),this.picker.addClass("datepicker-orient-"+p),"top"===p?n-=c+parseInt(this.picker.css("padding-top")):n+=k,this.o.rtl){var q=e-(m+l);this.picker.css({top:n,right:q,zIndex:i})}else this.picker.css({top:n,left:m,zIndex:i});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.inputField.val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return r.parseDate(a,this.o.format,this.o.language,this.o.assumeNearbyYear)},this)),c=a.grep(c,a.proxy(function(a){return!this.dateWithinRange(a)||!a},this),!0),this.dates.replace(c),this.o.updateViewDate&&(this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDate<this.o.startDate?this.viewDate=new Date(this.o.startDate):this.viewDate>this.o.endDate?this.viewDate=new Date(this.o.endDate):this.viewDate=this.o.defaultViewDate),d?(this.setValue(),this.element.change()):this.dates.length&&String(b)!==String(this.dates)&&d&&(this._trigger("changeDate"),this.element.change()),!this.dates.length&&b.length&&(this._trigger("clearDate"),this.element.change()),this.fill(),this},fillDow:function(){if(this.o.showWeekDays){var b=this.o.weekStart,c="<tr>";for(this.o.calendarWeeks&&(c+='<th class="cw"> </th>');b<this.o.weekStart+7;)c+='<th class="dow',-1!==a.inArray(b,this.o.daysOfWeekDisabled)&&(c+=" disabled"),c+='">'+q[this.o.language].daysMin[b++%7]+"</th>";c+="</tr>",this.picker.find(".datepicker-days thead").append(c)}},fillMonths:function(){for(var a,b=this._utc_to_local(this.viewDate),c="",d=0;d<12;d++)a=b&&b.getMonth()===d?" focused":"",c+='<span class="month'+a+'">'+q[this.o.language].monthsShort[d]+"</span>";this.picker.find(".datepicker-months td").html(c)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],f=this.viewDate.getUTCFullYear(),g=this.viewDate.getUTCMonth(),h=d();return b.getUTCFullYear()<f||b.getUTCFullYear()===f&&b.getUTCMonth()<g?c.push("old"):(b.getUTCFullYear()>f||b.getUTCFullYear()===f&&b.getUTCMonth()>g)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&e(b,h)&&c.push("today"),-1!==this.dates.contains(b)&&c.push("active"),this.dateWithinRange(b)||c.push("disabled"),this.dateIsDisabled(b)&&c.push("disabled","disabled-date"),-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekHighlighted)&&c.push("highlighted"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!==a.inArray(b.valueOf(),this.range)&&c.push("selected"),b.valueOf()===this.range[0]&&c.push("range-start"),b.valueOf()===this.range[this.range.length-1]&&c.push("range-end")),c},_fill_yearsView:function(c,d,e,f,g,h,i){for(var j,k,l,m="",n=e/10,o=this.picker.find(c),p=Math.floor(f/e)*e,q=p+9*n,r=Math.floor(this.viewDate.getFullYear()/n)*n,s=a.map(this.dates,function(a){return Math.floor(a.getUTCFullYear()/n)*n}),t=p-n;t<=q+n;t+=n)j=[d],k=null,t===p-n?j.push("old"):t===q+n&&j.push("new"),-1!==a.inArray(t,s)&&j.push("active"),(t<g||t>h)&&j.push("disabled"),t===r&&j.push("focused"),i!==a.noop&&(l=i(new Date(t,0,1)),l===b?l={}:"boolean"==typeof l?l={enabled:l}:"string"==typeof l&&(l={classes:l}),!1===l.enabled&&j.push("disabled"),l.classes&&(j=j.concat(l.classes.split(/\s+/))),l.tooltip&&(k=l.tooltip)),m+='<sp
15733an class="'+j.join(" ")+'"'+(k?' title="'+k+'"':"")+">"+t+"</span>";o.find(".datepicker-switch").text(p+"-"+q),o.find("td").html(m)},fill:function(){var e,f,g=new Date(this.viewDate),h=g.getUTCFullYear(),i=g.getUTCMonth(),j=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,k=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,l=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,m=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,n=q[this.o.language].today||q.en.today||"",o=q[this.o.language].clear||q.en.clear||"",p=q[this.o.language].titleFormat||q.en.titleFormat,s=d(),t=(!0===this.o.todayBtn||"linked"===this.o.todayBtn)&&s>=this.o.startDate&&s<=this.o.endDate&&!this.weekOfDateIsDisabled(s);if(!isNaN(h)&&!isNaN(i)){this.picker.find(".datepicker-days .datepicker-switch").text(r.formatDate(g,p,this.o.language)),this.picker.find("tfoot .today").text(n).css("display",t?"table-cell":"none"),this.picker.find("tfoot .clear").text(o).css("display",!0===this.o.clearBtn?"table-cell":"none"),this.picker.find("thead .datepicker-title").text(this.o.title).css("display","string"==typeof this.o.title&&""!==this.o.title?"table-cell":"none"),this.updateNavArrows(),this.fillMonths();var u=c(h,i,0),v=u.getUTCDate();u.setUTCDate(v-(u.getUTCDay()-this.o.weekStart+7)%7);var w=new Date(u);u.getUTCFullYear()<100&&w.setUTCFullYear(u.getUTCFullYear()),w.setUTCDate(w.getUTCDate()+42),w=w.valueOf();for(var x,y,z=[];u.valueOf()<w;){if((x=u.getUTCDay())===this.o.weekStart&&(z.push("<tr>"),this.o.calendarWeeks)){var A=new Date(+u+(this.o.weekStart-x-7)%7*864e5),B=new Date(Number(A)+(11-A.getUTCDay())%7*864e5),C=new Date(Number(C=c(B.getUTCFullYear(),0,1))+(11-C.getUTCDay())%7*864e5),D=(B-C)/864e5/7+1;z.push('<td class="cw">'+D+"</td>")}y=this.getClassNames(u),y.push("day");var E=u.getUTCDate();this.o.beforeShowDay!==a.noop&&(f=this.o.beforeShowDay(this._utc_to_local(u)),f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),!1===f.enabled&&y.push("disabled"),f.classes&&(y=y.concat(f.classes.split(/\s+/))),f.tooltip&&(e=f.tooltip),f.content&&(E=f.content)),y=a.isFunction(a.uniqueSort)?a.uniqueSort(y):a.unique(y),z.push('<td class="'+y.join(" ")+'"'+(e?' title="'+e+'"':"")+' data-date="'+u.getTime().toString()+'">'+E+"</td>"),e=null,x===this.o.weekEnd&&z.push("</tr>"),u.setUTCDate(u.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").html(z.join(""));var F=q[this.o.language].monthsTitle||q.en.monthsTitle||"Months",G=this.picker.find(".datepicker-months").find(".datepicker-switch").text(this.o.maxViewMode<2?F:h).end().find("tbody span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===h&&G.eq(b.getUTCMonth()).addClass("active")}),(h<j||h>l)&&G.addClass("disabled"),h===j&&G.slice(0,k).addClass("disabled"),h===l&&G.slice(m+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var H=this;a.each(G,function(c,d){var e=new Date(h,c,1),f=H.o.beforeShowMonth(e);f===b?f={}:"boolean"==typeof f?f={enabled:f}:"string"==typeof f&&(f={classes:f}),!1!==f.enabled||a(d).hasClass("disabled")||a(d).addClass("disabled"),f.classes&&a(d).addClass(f.classes),f.tooltip&&a(d).prop("title",f.tooltip)})}this._fill_yearsView(".datepicker-years","year",10,h,j,l,this.o.beforeShowYear),this._fill_yearsView(".datepicker-decades","decade",100,h,j,l,this.o.beforeShowDecade),this._fill_yearsView(".datepicker-centuries","century",1e3,h,j,l,this.o.beforeShowCentury)}},updateNavArrows:function(){if(this._allow_update){var a,b,c=new Date(this.viewDate),d=c.getUTCFullYear(),e=c.getUTCMonth(),f=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,g=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,h=this.o.endDate!==1/0?this.o.endDate.getUTCFullYear():1/0,i=this.o.endDate!==1/0?this.o.endDate.getUTCMonth():1/0,j=1;switch(this.viewMode){case 4:j*=10;case 3:j*=10;case 2:j*=10;case 1:a=Math.floor(d/j)*j<=f,b=Math.floor(d/j)*j+j>h;break;case 0:a=d<=f&&e<=g,b=d>=h&&e>=i}this.picker.find(".prev").toggleClass("disabled",a),this.picker.find(".next").toggleClass("disabled",b)}},click:function(b){b.preventDefault(),b.stopPropagation();var e,f,g,h;e=a(b.target),e.hasClass("datepicker-switch")&&this.viewMode!==this.o.maxViewMode&&this.setViewMode(this.viewMode+1),e.hasClass("today")&&!e.hasClass("day")&&(this.setViewMode(0),this._setDate(d(),"linked"===this.o.todayBtn?null:"view")),e.hasClass("clear")&&this.clearDates(),e.hasClass("disabled")||(e.hasClass("month")||e.hasClass("year")||e.hasClass("decade")||e.hasClass("century"))&&(this.viewDate.setUTCDate(1),f=1,1===this.viewMode?(h=e.parent().find("span").index(e),g=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(h)):(h=0,g=Number(e.text()),this.viewDate.setUTCFullYear(g)),this._trigger(r.viewModes[this.viewMode-1].e,this.viewDate),this.viewMode===this.o.minViewMode?this._setDate(c(g,h,f)):(this.setViewMode(this.viewMode-1),this.fill())),this.picker.is(":visible")&&this._focused_from&&this._focused_from.focus(),delete this._focused_from},dayCellClick:function(b){var c=a(b.currentTarget),d=c.data("date"),e=new Date(d);this.o.updateViewDate&&(e.getUTCFullYear()!==this.viewDate.getUTCFullYear()&&this._trigger("changeYear",this.viewDate),e.getUTCMonth()!==this.viewDate.getUTCMonth()&&this._trigger("changeMonth",this.viewDate)),this._setDate(e)},navArrowsClick:function(b){var c=a(b.currentTarget),d=c.hasClass("prev")?-1:1;0!==this.viewMode&&(d*=12*r.viewModes[this.viewMode].navStep),this.viewDate=this.moveMonth(this.viewDate,d),this._trigger(r.viewModes[this.viewMode].e,this.viewDate),this.fill()},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),-1!==b?(!0===this.o.multidate||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):!1===this.o.multidate?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)}
vendor: 6,432 bytes, line 15733
15733,_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),(!b&&this.o.updateViewDate||"view"===b)&&(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate"),this.inputField.trigger("change"),!this.o.autoclose||b&&"date"!==b||this.hide()},moveDay:function(a,b){var c=new Date(a);return c.setUTCDate(a.getUTCDate()+b),c},moveWeek:function(a,b){return this.moveDay(a,7*b)},moveMonth:function(a,b){if(!g(a))return this.o.defaultViewDate;if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),h=e.getUTCMonth(),i=Math.abs(b);if(b=b>0?1:-1,1===i)d=-1===b?function(){return e.getUTCMonth()===h}:function(){return e.getUTCMonth()!==c},c=h+b,e.setUTCMonth(c),c=(c+12)%12;else{for(var j=0;j<i;j++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!==e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},moveAvailableDate:function(a,b,c){do{if(a=this[c](a,b),!this.dateWithinRange(a))return!1;c="moveDay"}while(this.dateIsDisabled(a));return a},weekOfDateIsDisabled:function(b){return-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled)},dateIsDisabled:function(b){return this.weekOfDateIsDisabled(b)||a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void(40!==a.keyCode&&27!==a.keyCode||(this.show(),a.stopPropagation()));var b,c,d=!1,e=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault(),a.stopPropagation();break;case 37:case 38:case 39:case 40:if(!this.o.keyboardNavigation||7===this.o.daysOfWeekDisabled.length)break;b=37===a.keyCode||38===a.keyCode?-1:1,0===this.viewMode?a.ctrlKey?(c=this.moveAvailableDate(e,b,"moveYear"))&&this._trigger("changeYear",this.viewDate):a.shiftKey?(c=this.moveAvailableDate(e,b,"moveMonth"))&&this._trigger("changeMonth",this.viewDate):37===a.keyCode||39===a.keyCode?c=this.moveAvailableDate(e,b,"moveDay"):this.weekOfDateIsDisabled(e)||(c=this.moveAvailableDate(e,b,"moveWeek")):1===this.viewMode?(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveMonth")):2===this.viewMode&&(38!==a.keyCode&&40!==a.keyCode||(b*=4),c=this.moveAvailableDate(e,b,"moveYear")),c&&(this.focusDate=this.viewDate=c,this.setValue(),this.fill(),a.preventDefault());break;case 13:if(!this.o.forceParse)break;e=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(e),d=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),a.stopPropagation(),this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}d&&(this.dates.length?this._trigger("changeDate"):this._trigger("clearDate"),this.inputField.trigger("change"))},setViewMode:function(a){this.viewMode=a,this.picker.children("div").hide().filter(".datepicker-"+r.viewModes[this.viewMode].clsName).show(),this.updateNavArrows(),this._trigger("changeViewMode",new Date(this.viewDate))}};var l=function(b,c){a.data(b,"datepicker",this),this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,this.keepEmptyValues=c.keepEmptyValues,delete c.keepEmptyValues,n.call(a(this.inputs),c).on("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a.data(b,"datepicker")}),this.updateDates()};l.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},clearDates:function(){a.each(this.pickers,function(a,b){b.clearDates()})},dateUpdated:function(c){if(!this.updating){this.updating=!0;var d=a.data(c.target,"datepicker");if(d!==b){var e=d.getUTCDate(),f=this.keepEmptyValues,g=a.inArray(c.target,this.inputs),h=g-1,i=g+1,j=this.inputs.length;if(-1!==g){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b!==d&&f||b.setUTCDate(e)}),e<this.dates[h])for(;h>=0&&e<this.dates[h];)this.pickers[h--].setUTCDate(e);else if(e>this.dates[i])for(;i<j&&e>this.dates[i];)this.pickers[i++].setUTCDate(e);this.updateDates(),delete this.updating}}}},destroy:function(){a.map(this.pickers,function(a){a.destroy()}),a(this.inputs).off("changeDate",this.dateUpdated),delete this.element.data().datepicker},remove:f("destroy","Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead")};var m=a.fn.datepicker,n=function(c){var d=Array.apply(null,arguments);d.shift();var e;if(this.each(function(){var b=a(this),f=b.data("datepicker"),g="object"==typeof c&&c;if(!f){var j=h(this,"date"),m=a.extend({},o,j,g),n=i(m.language),p=a.extend({},o,n,j,g);b.hasClass("input-daterange")||p.inputs?(a.extend(p,{inputs:p.inputs||b.find("input").toArray()}),f=new l(this,p)):f=new k(this,p),b.data("datepicker",f)}"string"==typeof c&&"function"==typeof f[c]&&(e=f[c].apply(f,d))}),e===b||e instanceof k||e instanceof l)return this;if(this.length>1)throw new Error("Using only allowed for the collection of a single element ("+c+" function)");return e};a.fn.datepicker=n;var o=a.fn.datepicker.defaults={assumeNearbyYear:!1,autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,beforeShowYear:a.noop,beforeShowDecade:a.noop,beforeShowCentury:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],daysOfWeekHighlighted:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keepEmptyValues:!1,keyboardNavigation:!0,language:"en",minViewMode:0,maxViewMode:4,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,updateViewDate:!0,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,showOnFocus:!0,zIndexOffset:10,container:"body",immediateUpdates:!1,title:"",templates:{leftArrow:"«",rightArrow:"»"},showWeekDays:!0},p=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=k;var q=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
15733ay","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear",titleFormat:"MM yyyy"}},r={viewModes:[{names:["days","month"],clsName:"days",e:"changeMonth"},{names:["months","year"],clsName:"months",e:"changeYear",navStep:1},{names:["years","decade"],clsName:"years",e:"changeDecade",navStep:10},{names:["decades","century"],clsName:"decades",e:"changeCentury",navStep:100},{names:["centuries","millennium"],clsName:"centuries",e:"changeMillennium",navStep:1e3}],validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,parseFormat:function(a){if("function"==typeof a.toValue&&"function"==typeof a.toDisplay)return a;var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f,g){function h(a,b){return!0===b&&(b=10),a<100&&(a+=2e3)>(new Date).getFullYear()+b&&(a-=100),a}function i(){var a=this.slice(0,j[n].length),b=j[n].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!c)return b;if(c instanceof Date)return c;if("string"==typeof e&&(e=r.parseFormat(e)),e.toValue)return e.toValue(c,e,f);var j,l,m,n,o,p={d:"moveDay",m:"moveMonth",w:"moveWeek",y:"moveYear"},s={yesterday:"-1d",today:"+0d",tomorrow:"+1d"};if(c in s&&(c=s[c]),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(c)){for(j=c.match(/([\-+]\d+)([dmwy])/gi),c=new Date,n=0;n<j.length;n++)l=j[n].match(/([\-+]\d+)([dmwy])/i),m=Number(l[1]),o=p[l[2].toLowerCase()],c=k.prototype[o](c,m);return k.prototype._zero_utc_time(c)}j=c&&c.match(this.nonpunctuation)||[];var t,u,v={},w=["yyyy","yy","M","MM","m","mm","d","dd"],x={yyyy:function(a,b){return a.setUTCFullYear(g?h(b,g):b)},m:function(a,b){if(isNaN(a))return a;for(b-=1;b<0;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};x.yy=x.yyyy,x.M=x.MM=x.mm=x.m,x.dd=x.d,c=d();var y=e.parts.slice();if(j.length!==y.length&&(y=a(y).filter(function(b,c){return-1!==a.inArray(c,w)}).toArray()),j.length===y.length){var z;for(n=0,z=y.length;n<z;n++){if(t=parseInt(j[n],10),l=y[n],isNaN(t))switch(l){case"MM":u=a(q[f].months).filter(i),t=a.inArray(u[0],q[f].months)+1;break;case"M":u=a(q[f].monthsShort).filter(i),t=a.inArray(u[0],q[f].monthsShort)+1}v[l]=t}var A,B;for(n=0;n<w.length;n++)(B=w[n])in v&&!isNaN(v[B])&&(A=new Date(c),x[B](A,v[B]),isNaN(A)||(c=A))}return c},formatDate:function(b,c,d){if(!b)return"";if("string"==typeof c&&(c=r.parseFormat(c)),c.toDisplay)return c.toDisplay(b,c,d);var e={d:b.getUTCDate(),D:q[d].daysShort[b.getUTCDay()],DD:q[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:q[d].monthsShort[b.getUTCMonth()],MM:q[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m,b=[];for(var f=a.extend([],c.separators),g=0,h=c.parts.length;g<=h;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")}, 15734headTemplate:'<thead><tr><th colspan="7" class="datepicker-title"></th></tr><tr><th class="prev">'+o.templates.leftArrow+'</th><th colspan="5" class="datepicker-switch"></th><th class="next">'+o.templates.rightArrow+"</th></tr></thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};r.template='<div class="datepicker"><div class="datepicker-days"><table class="table-condensed">'+r.headTemplate+"<tbody></tbody>"+r.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-decades"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+'</table></div><div class="datepicker-centuries"><table class="table-condensed">'+r.headTemplate+r.contTemplate+r.footTemplate+"</table></div></div>",a.fn.datepicker.DPGlobal=r,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=m,this},a.fn.datepicker.version="1.9.0",a.fn.datepicker.deprecated=function(a){var b=window.console;b&&b.warn&&b.warn("DEPRECATED: "+a)},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),n.call(c,"show"))}),a(function(){n.call(a('[data-provide="datepicker-inline"]'))})}); 15735"use strict"; 15736$.fn.datepicker.defaults.zIndexOffset = 10;
15737(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof exports==="object"){a(require("jquery"))}else{a(jQuery)}}}(function(d,f){if(!("indexOf" in Array.prototype)){Array.prototype.indexOf=function(k,j){if(j===f){j=0}if(j<0){j+=this.length}if(j<0){j=0}for(var l=this.length;j<l;j++){if(j in this&&this[j]===k){return j}}return -1}}function a(){var q,k,p,l,j,n,m,o;k=(new Date()).toString();p=((m=k.split("(")[1])!=null?m.slice(0,-1):0)||k.split(" ");if(p instanceof Array){n=[];for(var l=0,j=p.length;l<j;l++){o=p[l];if((q=(m=o.match(/\b[A-Z]+\b/))!==null)?m[0]:0){n.push(q)}}p=n.pop()}return p}function h(){return new Date(Date.UTC.apply(Date,arguments))}var g=function(k,j){var m=this;this.element=d(k);this.container=j.container||"body";this.language=j.language||this.element.data("date-language")||"en";this.language=this.language in e?this.language:this.language.split("-")[0];this.language=this.language in e?this.language:"en";this.isRTL=e[this.language].rtl||false;this.formatType=j.formatType||this.element.data("format-type")||"standard";this.format=c.parseFormat(j.format||this.element.data("date-format")||e[this.language].format||c.getDefaultFormat(this.formatType,"input"),this.formatType);this.isInline=false;this.isVisible=false;this.isInput=this.element.is("input");this.fontAwesome=j.fontAwesome||this.element.data("font-awesome")||false;this.bootcssVer=j.bootcssVer||(this.isInput?(this.element.is(".form-control")?3:2):(this.bootcssVer=this.element.is(".input-group")?3:2));this.component=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o").parent():this.element.find(".add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o").parent()):false;this.componentReset=this.element.is(".date")?(this.bootcssVer===3?this.element.find(".input-group-addon .glyphicon-remove, .input-group-addon .fa-times").parent():this.element.find(".add-on .icon-remove, .add-on .fa-times").parent()):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0){this.component=false}this.linkField=j.linkField||this.element.data("link-field")||false;this.linkFormat=c.parseFormat(j.linkFormat||this.element.data("link-format")||c.getDefaultFormat(this.formatType,"link"),this.formatType);this.minuteStep=j.minuteStep||this.element.data("minute-step")||5;this.pickerPosition=j.pickerPosition||this.element.data("picker-position")||"bottom-right";this.showMeridian=j.showMeridian||this.element.data("show-meridian")||false;this.initialDate=j.initialDate||new Date();this.zIndex=j.zIndex||this.element.data("z-index")||f;this.title=typeof j.title==="undefined"?false:j.title;this.timezone=j.timezone||a();this.icons={leftArrow:this.fontAwesome?"fa-arrow-left":(this.bootcssVer===3?"glyphicon-arrow-left":"icon-arrow-left"),rightArrow:this.fontAwesome?"fa-arrow-right":(this.bootcssVer===3?"glyphicon-arrow-right":"icon-arrow-right")};this.icontype=this.fontAwesome?"fa":"glyphicon";this._attachEvents();this.clickedOutside=function(n){if(d(n.target).closest(".datetimepicker").length===0){m.hide()}};this.formatViewType="datetime";if("formatViewType" in j){this.formatViewType=j.formatViewType}else{if("formatViewType" in this.element.data()){this.formatViewType=this.element.data("formatViewType")}}this.minView=0;if("minView" in j){this.minView=j.minView}else{if("minView" in this.element.data()){this.minView=this.element.data("min-view")}}this.minView=c.convertViewMode(this.minView);this.maxView=c.modes.length-1;if("maxView" in j){this.maxView=j.maxView}else{if("maxView" in this.element.data()){this.maxView=this.element.data("max-view")}}this.maxView=c.convertViewMode(this.maxView);this.wheelViewModeNavigation=false;if("wheelViewModeNavigation" in j){this.wheelViewModeNavigation=j.wheelViewModeNavigation}else{if("wheelViewModeNavigation" in this.element.data()){this.wheelViewModeNavigation=this.element.data("view-mode-wheel-navigation")}}this.wheelViewModeNavigationInverseDirection=false;if("wheelViewModeNavigationInverseDirection" in j){this.wheelViewModeNavigationInverseDirection=j.wheelViewModeNavigationInverseDirection}else{if("wheelViewModeNavigationInverseDirection" in this.element.data()){this.wheelViewModeNavigationInverseDirection=this.element.data("view-mode-wheel-navigation-inverse-dir")}}this.wheelViewModeNavigationDelay=100;if("wheelViewModeNavigationDelay" in j){this.wheelViewModeNavigationDelay=j.wheelViewModeNavigationDelay}else{if("wheelViewModeNavigationDelay" in this.element.data()){this.wheelViewModeNavigationDelay=this.element.data("view-mode-wheel-navigation-delay")}}this.startViewMode=2;if("startView" in j){this.startViewMode=j.startView}else{if("startView" in this.element.data()){this.startViewMode=this.element.data("start-view")}}this.startViewMode=c.convertViewMode(this.startViewMode);this.viewMode=this.startViewMode;this.viewSelect=this.minView;if("viewSelect" in j){this.viewSelect=j.viewSelect}else{if("viewSelect" in this.element.data()){this.viewSelect=this.element.data("view-select")}}this.viewSelect=c.convertViewMode(this.viewSelect);this.forceParse=true;if("forceParse" in j){this.forceParse=j.forceParse}else{if("dateForceParse" in this.element.data()){this.forceParse=this.element.data("date-force-parse")}}var l=this.bootcssVer===3?c.templateV3:c.template;while(l.indexOf("{iconType}")!==-1){l=l.replace("{iconType}",this.icontype)}while(l.indexOf("{leftArrow}")!==-1){l=l.replace("{leftArrow}",this.icons.leftArrow)}while(l.indexOf("{rightArrow}")!==-1){l=l.replace("{rightArrow}",this.icons.rightArrow)}this.picker=d(l).appendTo(this.isInline?this.element:this.container).on({click:d.proxy(this.click,this),mousedown:d.proxy(this.mousedown,this)});if(this.wheelViewModeNavigation){if(d.fn.mousewheel){this.picker.on({mousewheel:d.proxy(this.mousewheel,this)})}else{console.log("Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option")}}if(this.isInline){this.picker.addClass("datetimepicker-inline")}else{this.picker.addClass("datetimepicker-dropdown-"+this.pickerPosition+" dropdown-menu")}if(this.isRTL){this.picker.addClass("datetimepicker-rtl");var i=this.bootcssVer===3?".prev span, .next span":".prev i, .next i";this.picker.find(i).toggleClass(this.icons.leftArrow+" "+this.icons.rightArrow)}d(document).on("mousedown touchend",this.clickedOutside);this.autoclose=false;if("autoclose" in j){this.autoclose=j.autoclose}else{if("dateAutoclose" in this.element.data()){this.autoclose=this.element.data("date-autoclose")}}this.keyboardNavigation=true;if("keyboardNavigation" in j){this.keyboardNavigation=j.keyboardNavigation}else{if("dateKeyboardNavigation" in this.element.data()){this.keyboardNavigation=this.element.data("date-keyboard-navigation")}}this.todayBtn=(j.todayBtn||this.element.data("date-today-btn")||false);this.clearBtn=(j.clearBtn||this.element.data("date-clear-btn")||false);this.todayHighlight=(j.todayHighlight||this.element.data("date-today-highlight")||false);this.weekStart=0;if(typeof j.weekStart!=="undefined"){this.weekStart=j.weekStart}else{if(typeof this.element.data("date-weekstart")!=="undefined"){this.weekStart=this.element.data("date-weekstart")}else{if(typeof e[this.language].weekStart!=="undefined"){this.weekStart=e[this.language].weekStart}}}this.weekStart=this.weekStart%7;this.weekEnd=((this.weekStart+6)%7);this.onRenderDay=function(n){var p=(j.onRenderDay||function(){return[]})(n);if(typeof p==="string"){p=[p]}var o=["day"];return o.concat((p?p:[]))};this.onRenderHour=function(n){var p=(j.onRenderHour||function(){return[]})(n);var o=["hour"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.onRenderMinute=function(n){var p=(j.onRenderMinute||function(){return[]})(n);var o=["minute"];if(typeof p==="string"){p=[p]}if(n<this.startDate||n>this.endDate){o.push("disabled")}else{if(Math.floor(this.date.getUTCMinutes()/this.minuteStep)===Math.floor(n.getUTCMinutes()/this.minuteStep)){o.push("active")}}return o.concat((p?p:[]))};this.onRenderYear=function(o){var q=(j.onRenderYear||function(){return[]})(o);var p=["year"];if(typeof q==="string"){q=[q]}if(this.date.getUTCFullYear()===o.getUTCFullYear()){p.push("active")}var n=o.getUTCFullYear();var r=this.endDate.getUTCFullYear();if(o<this.startDate||n>r){p.push("disabled")}return p.concat((q?q:[]))};this.onRenderMonth=function(n){var p=(j.onRenderMonth||function(){return[]})(n);var o=["month"];if(typeof p==="string"){p=[p]}return o.concat((p?p:[]))};this.startDate=new Date(-8639968443048000);this.endDate=new Date(8639968443048000);this.datesDisabled=[];this.daysOfWeekDisabled=[];this.setStartDate(j.startDate||this.element.data("date-startdate"));this.setEndDate(j.endDate||this.element.data("date-enddate"));this.setDatesDisabled(j.datesDisabled||this.element.data("date-dates-disabled"));this.setDaysOfWeekDisabled(j.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled"));this.setMinutesDisabled(j.minutesDisabled||this.element.data("date-minute-disabled"));this.setHoursDisabled(j.hoursDisabled||this.element.data("date-hour-disabled"));this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.show()}};g.prototype={constructor:g,_events:[],_attachEvents:function(){this._detachEvents();if(this.isInput){this._events=[[this.element,{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}]]}else{if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:d.proxy(this.show,this),keyup:d.proxy(this.update,this),keydown:d.proxy(this.keydown,this)}],[this.component,{click:d.proxy(this.show,this)}]];if(this.componentReset){this._events.push([this.componentReset,{click:d.proxy(this.reset,this)}])}}else{if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:d.proxy(this.show,this)}]]}}}for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.on(l)}},_detachEvents:function(){for(var j=0,k,l;j<this._events.length;j++){k=this._events[j][0];l=this._events[j][1];k.off(l)}this._events=[]},show:function(i){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();if(this.forceParse){this.update()}this.place();d(window).on("resize",d.proxy(this.place,this));if(i){i.stopPropagation();i.preventDefault()}this.isVisible=true;this.element.trigger({type:"show",date:this.date})},hide:function(){if(!this.isVisible){return}if(this.isInline){return}this.picker.hide();d(window).off("resize",this.place);this.viewMode=this.startViewMode;this.showMode();if(!this.isInput){d(document).off("mousedown",this.hide)}if(this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())){this.setValue()}this.isVisible=false;this.element.trigger({type:"hide",date:this.date})},remove:function(){this._detachEvents();d(document).off("mousedown",this.clickedOutside);this.picker.remove();delete this.picker;delete this.element.data().datetimepicker},getDate:function(){var i=this.getUTCDate();if(i===null){return null}return new Date(i.getTime()+(i.getTimezoneOffset()*60000))},getUTCDate:function(){return this.date},getInitialDate:function(){return this.initialDate},setInitialDate:function(i){this.initialDate=i},setDate:function(i){this.setUTCDate(new Date(i.getTime()-(i.getTimezoneOffset()*60000)))},setUTCDate:function(i){if(i>=this.startDate&&i<=this.endDate){this.date=i;this.setValue();this.viewDate=this.date;this.fill()}else{this.element.trigger({type:"outOfRange",date:i,startDate:this.startDate,endD
15737ate:this.endDate})}},setFormat:function(j){this.format=c.parseFormat(j,this.formatType);var i;if(this.isInput){i=this.element}else{if(this.component){i=this.element.find("input")}}if(i&&i.val()){this.setValue()}},setValue:function(){var i=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(i)}this.element.data("date",i)}else{this.element.val(i)}if(this.linkField){d("#"+this.linkField).val(this.getFormattedDate(this.linkFormat))}},getFormattedDate:function(i){i=i||this.format;return c.formatDate(this.date,i,this.language,this.formatType,this.timezone)},setStartDate:function(i){this.startDate=i||this.startDate;if(this.startDate.valueOf()!==8639968443048000){this.startDate=c.parseDate(this.startDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setEndDate:function(i){this.endDate=i||this.endDate;if(this.endDate.valueOf()!==8639968443048000){this.endDate=c.parseDate(this.endDate,this.format,this.language,this.formatType,this.timezone)}this.update();this.updateNavArrows()},setDatesDisabled:function(j){this.datesDisabled=j||[];if(!d.isArray(this.datesDisabled)){this.datesDisabled=this.datesDisabled.split(/,\s*/)}var i=this;this.datesDisabled=d.map(this.datesDisabled,function(k){return c.parseDate(k,i.format,i.language,i.formatType,i.timezone).toDateString()});this.update();this.updateNavArrows()},setTitle:function(i,j){return this.picker.find(i).find("th:eq(1)").text(this.title===false?j:this.title)},setDaysOfWeekDisabled:function(i){this.daysOfWeekDisabled=i||[];if(!d.isArray(this.daysOfWeekDisabled)){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)}this.daysOfWeekDisabled=d.map(this.daysOfWeekDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setMinutesDisabled:function(i){this.minutesDisabled=i||[];if(!d.isArray(this.minutesDisabled)){this.minutesDisabled=this.minutesDisabled.split(/,\s*/)}this.minutesDisabled=d.map(this.minutesDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},setHoursDisabled:function(i){this.hoursDisabled=i||[];if(!d.isArray(this.hoursDisabled)){this.hoursDisabled=this.hoursDisabled.split(/,\s*/)}this.hoursDisabled=d.map(this.hoursDisabled,function(j){return parseInt(j,10)});this.update();this.updateNavArrows()},place:function(){if(this.isInline){return}if(!this.zIndex){var j=0;d("div").each(function(){var o=parseInt(d(this).css("zIndex"),10);if(o>j){j=o}});this.zIndex=j+10}var n,m,l,k;if(this.container instanceof d){k=this.container.offset()}else{k=d(this.container).offset()}if(this.component){n=this.component.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.component.outerWidth()-this.picker.outerWidth()}}else{n=this.element.offset();l=n.left;if(this.pickerPosition==="bottom-left"||this.pickerPosition==="top-left"){l+=this.element.outerWidth()-this.picker.outerWidth()}}var i=document.body.clientWidth||window.innerWidth;if(l+220>i){l=i-220}if(this.pickerPosition==="top-left"||this.pickerPosition==="top-right"){m=n.top-this.picker.outerHeight()}else{m=n.top+this.height}m=m-k.top;l=l-k.left;this.picker.css({top:m,left:l,zIndex:this.zIndex})},hour_minute:"^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]",update:function(){var i,j=false;if(arguments&&arguments.length&&(typeof arguments[0]==="string"||arguments[0] instanceof Date)){i=arguments[0];j=true}else{i=(this.isInput?this.element.val():this.element.find("input").val())||this.element.data("date")||this.initialDate;if(typeof i==="string"){i=i.replace(/^\s+|\s+$/g,"")}}if(!i){i=new Date();j=false}if(typeof i==="string"){if(new RegExp(this.hour_minute).test(i)||new RegExp(this.hour_minute+":[0-5][0-9]").test(i)){i=this.getDate()}}this.date=c.parseDate(i,this.format,this.language,this.formatType,this.timezone);if(j){this.setValue()}if(this.date<this.startDate){this.viewDate=new Date(this.startDate)}else{if(this.date>this.endDate){this.viewDate=new Date(this.endDate)}else{this.viewDate=new Date(this.date)}}this.fill()},fillDow:function(){var i=this.weekStart,j="<tr>";while(i<this.weekStart+7){j+='<th class="dow">'+e[this.language].daysMin[(i++)%7]+"</th>"}j+="</tr>";this.picker.find(".datetimepicker-days thead").append(j)},fillMonths:function(){var l="";var m=new Date(this.viewDate);for(var k=0;k<12;k++){m.setUTCMonth(k);var j=this.onRenderMonth(m);l+='<span class="'+j.join(" ")+'">'+e[this.language].monthsShort[k]+"</span>"}this.picker.find(".datetimepicker-months td").html(l)},fill:function(){if(!this.date||!this.viewDate){return}var E=new Date(this.viewDate),t=E.getUTCFullYear(),G=E.getUTCMonth(),n=E.getUTCDate(),A=E.getUTCHours(),w=this.startDate.getUTCFullYear(),B=this.startDate.getUTCMonth(),p=this.endDate.getUTCFullYear(),x=this.endDate.getUTCMonth()+1,q=(new h(this.date.getUTCFullYear(),this.date.getUTCMonth(),this.date.getUTCDate())).valueOf(),D=new Date();this.setTitle(".datetimepicker-days",e[this.language].months[G]+" "+t);if(this.formatViewType==="time"){var k=this.getFormattedDate();this.setTitle(".datetimepicker-hours",k);this.setTitle(".datetimepicker-minutes",k)}else{this.setTitle(".datetimepicker-hours",n+" "+e[this.language].months[G]+" "+t);this.setTitle(".datetimepicker-minutes",n+" "+e[this.language].months[G]+" "+t)}this.picker.find("tfoot th.today").text(e[this.language].today||e.en.today).toggle(this.todayBtn!==false);this.picker.find("tfoot th.clear").text(e[this.language].clear||e.en.clear).toggle(this.clearBtn!==false);this.updateNavArrows();this.fillMonths();var I=h(t,G-1,28,0,0,0,0),z=c.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());I.setUTCDate(z);I.setUTCDate(z-(I.getUTCDay()-this.weekStart+7)%7);var j=new Date(I);j.setUTCDate(j.getUTCDate()+42);j=j.valueOf();var r=[];var F;
15737while(I.valueOf()<j){if(I.getUTCDay()===this.weekStart){r.push("<tr>")}F=this.onRenderDay(I);if(I.getUTCFullYear()<t||(I.getUTCFullYear()===t&&I.getUTCMonth()<G)){F.push("old")}else{if(I.getUTCFullYear()>t||(I.getUTCFullYear()===t&&I.getUTCMonth()>G)){F.push("new")}}if(this.todayHighlight&&I.getUTCFullYear()===D.getFullYear()&&I.getUTCMonth()===D.getMonth()&&I.getUTCDate()===D.getDate()){F.push("today")}if(I.valueOf()===q){F.push("active")}if((I.valueOf()+86400000)<=this.startDate||I.valueOf()>this.endDate||d.inArray(I.getUTCDay(),this.daysOfWeekDisabled)!==-1||d.inArray(I.toDateString(),this.datesDisabled)!==-1){F.push("disabled")}r.push('<td class="'+F.join(" ")+'">'+I.getUTCDate()+"</td>");if(I.getUTCDay()===this.weekEnd){r.push("</tr>")}I.setUTCDate(I.getUTCDate()+1)}this.picker.find(".datetimepicker-days tbody").empty().append(r.join(""));r=[];var u="",C="",s="";var l=this.hoursDisabled||[];E=new Date(this.viewDate);for(var y=0;y<24;y++){E.setUTCHours(y);F=this.onRenderHour(E);if(l.indexOf(y)!==-1){F.push("disabled")}var v=h(t,G,n,y);if((v.valueOf()+3600000)<=this.startDate||v.valueOf()>this.endDate){F.push("disabled")}else{if(A===y){F.push("active")}}if(this.showMeridian&&e[this.language].meridiem.length===2){C=(y<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="hour"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(y%12?y%12:12);if(y<12){F.push("hour_am")}else{F.push("hour_pm")}r.push('<span class="'+F.join(" ")+'">'+u+"</span>");if(y===23){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+u+"</span>")}}this.picker.find(".datetimepicker-hours td").html(r.join(""));r=[];u="";C="";s="";var m=this.minutesDisabled||[];E=new Date(this.viewDate);for(var y=0;y<60;y+=this.minuteStep){if(m.indexOf(y)!==-1){continue}E.setUTCMinutes(y);E.setUTCSeconds(0);F=this.onRenderMinute(E);if(this.showMeridian&&e[this.language].meridiem.length===2){C=(A<12?e[this.language].meridiem[0]:e[this.language].meridiem[1]);if(C!==s){if(s!==""){r.push("</fieldset>")}r.push('<fieldset class="minute"><legend>'+C.toUpperCase()+"</legend>")}s=C;u=(A%12?A%12:12);r.push('<span class="'+F.join(" ")+'">'+u+":"+(y<10?"0"+y:y)+"</span>");if(y===59){r.push("</fieldset>")}}else{u=y+":00";r.push('<span class="'+F.join(" ")+'">'+A+":"+(y<10?"0"+y:y)+"</span>")}}this.picker.find(".datetimepicker-minutes td").html(r.join(""));var J=this.date.getUTCFullYear();var o=this.setTitle(".datetimepicker-months",t).end().find(".month").removeClass("active");if(J===t){o.eq(this.date.getUTCMonth()).addClass("active")}if(t<w||t>p){o.addClass("disabled")}if(t===w){o.slice(0,B).addClass("disabled")}if(t===p){o.slice(x).addClass("disabled")}r="";t=parseInt(t/10,10)*10;var H=this.setTitle(".datetimepicker-years",t+"-"+(t+9)).end().find("td");t-=1;E=new Date(this.viewDate);for(var y=-1;y<11;y++){E.setUTCFullYear(t);F=this.onRenderYear(E);if(y===-1||y===10){F.push(b)}r+='<span class="'+F.join(" ")+'">'+t+"</span>";t+=1}H.html(r);this.place()},updateNavArrows:function(){var m=new Date(this.viewDate),k=m.getUTCFullYear(),l=m.getUTCMonth(),j=m.getUTCDate(),i=m.getUTCHours();switch(this.viewMode){case 0:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()&&i<=this.startDate.getUTCHours()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()&&i>=this.endDate.getUTCHours()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()&&j<=this.startDate.getUTCDate()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()&&j>=this.endDate.getUTCDate()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 2:if(k<=this.startDate.getUTCFullYear()&&l<=this.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()&&l>=this.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 3:case 4:if(k<=this.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(k>=this.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},mousewheel:function(j){j.preventDefault();j.stopPropagation();if(this.wheelPause){return}this.wheelPause=true;var i=j.originalEvent;var l=i.wheelDelta;var k=l>0?1:(l===0)?0:-1;
15737if(this.wheelViewModeNavigationInverseDirection){k=-k}this.showMode(k);setTimeout(d.proxy(function(){this.wheelPause=false},this),this.wheelViewModeNavigationDelay)},click:function(m){m.stopPropagation();m.preventDefault();var n=d(m.target).closest("span, td, th, legend");if(n.is("."+this.icontype)){n=d(n).parent().closest("span, td, th, legend")}if(n.length===1){if(n.is(".disabled")){this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});return}switch(n[0].nodeName.toLowerCase()){case"th":switch(n[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=c.modes[this.viewMode].navStep*(n[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,i);break;case 1:this.viewDate=this.moveDate(this.viewDate,i);break;case 2:this.viewDate=this.moveMonth(this.viewDate,i);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,i);break}this.fill();this.element.trigger({type:n[0].className+":"+this.convertViewModeText(this.viewMode),date:this.viewDate,startDate:this.startDate,endDate:this.endDate});break;case"clear":this.reset();if(this.autoclose){this.hide()}break;case"today":var j=new Date();j=h(j.getFullYear(),j.getMonth(),j.getDate(),j.getHours(),j.getMinutes(),j.getSeconds(),0);if(j<this.startDate){j=this.startDate}else{if(j>this.endDate){j=this.endDate}}this.viewMode=this.startViewMode;this.showMode(0);this._setDate(j);this.fill();if(this.autoclose){this.hide()}break}break;case"span":if(!n.is(".disabled")){var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),q=this.viewDate.getUTCDate(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".month")){this.viewDate.setUTCDate(1);o=n.parent().find("span").index(n);q=this.viewDate.getUTCDate();this.viewDate.setUTCMonth(o);this.element.trigger({type:"changeMonth",date:this.viewDate});if(this.viewSelect>=3){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".year")){this.viewDate.setUTCDate(1);p=parseInt(n.text(),10)||0;this.viewDate.setUTCFullYear(p);this.element.trigger({type:"changeYear",date:this.viewDate});if(this.viewSelect>=4){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".hour")){r=parseInt(n.text(),10)||0;if(n.hasClass("hour_am")||n.hasClass("hour_pm")){if(r===12&&n.hasClass("hour_am")){r=0}else{if(r!==12&&n.hasClass("hour_pm")){r+=12}}}this.viewDate.setUTCHours(r);this.element.trigger({type:"changeHour",date:this.viewDate});if(this.viewSelect>=1){this._setDate(h(p,o,q,r,k,s,0))}}else{if(n.is(".minute")){k=parseInt(n.text().substr(n.text().indexOf(":")+1),10)||0;this.viewDate.setUTCMinutes(k);this.element.trigger({type:"changeMinute",date:this.viewDate});if(this.viewSelect>=0){this._setDate(h(p,o,q,r,k,s,0))}}}}}if(this.viewMode!==0){var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}}break;case"td":if(n.is(".day")&&!n.is(".disabled")){var q=parseInt(n.text(),10)||1;var p=this.viewDate.getUTCFullYear(),o=this.viewDate.getUTCMonth(),r=this.viewDate.getUTCHours(),k=this.viewDate.getUTCMinutes(),s=this.viewDate.getUTCSeconds();if(n.is(".old")){if(o===0){o=11;p-=1}else{o-=1}}else{if(n.is(".new")){if(o===11){o=0;p+=1}else{o+=1}}}this.viewDate.setUTCFullYear(p);this.viewDate.setUTCMonth(o,q);this.element.trigger({type:"changeDay",date:this.viewDate});if(this.viewSelect>=2){this._setDate(h(p,o,q,r,k,s,0))}}var l=this.viewMode;this.showMode(-1);this.fill();if(l===this.viewMode&&this.autoclose){this.hide()}break}}},_setDate:function(i,k){if(!k||k==="date"){this.date=i}if(!k||k==="view"){this.viewDate=i}this.fill();this.setValue();var j;if(this.isInput){j=this.element}else{if(this.component){j=this.element.find("input")}}if(j){j.change()}this.element.trigger({type:"changeDate",date:this.getDate()});if(i===null){this.date=this.viewDate}},moveMinute:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCMinutes(k.getUTCMinutes()+(i*this.minuteStep));return k},moveHour:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCHours(k.getUTCHours()+i);return k}
15737,moveDate:function(j,i){if(!i){return j}var k=new Date(j.valueOf());k.setUTCDate(k.getUTCDate()+i);return k},moveMonth:function(j,k){if(!k){return j}var n=new Date(j.valueOf()),r=n.getUTCDate(),o=n.getUTCMonth(),m=Math.abs(k),q,p;k=k>0?1:-1;if(m===1){p=k===-1?function(){return n.getUTCMonth()===o}:function(){return n.getUTCMonth()!==q};q=o+k;n.setUTCMonth(q);if(q<0||q>11){q=(q+12)%12}}else{for(var l=0;l<m;l++){n=this.moveMonth(n,k)}q=n.getUTCMonth();n.setUTCDate(r);p=function(){return q!==n.getUTCMonth()}}while(p()){n.setUTCDate(--r);n.setUTCMonth(q)}return n},moveYear:function(j,i){return this.moveMonth(j,i*12)},dateWithinRange:function(i){return i>=this.startDate&&i<=this.endDate},keydown:function(o){if(this.picker.is(":not(:visible)")){if(o.keyCode===27){this.show()}return}var k=false,j,i,n;switch(o.keyCode){case 27:this.hide();o.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break}j=o.keyCode===37?-1:1;var m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j);n=this.moveDate(this.viewDate,j)}else{if(m===1){i=this.moveHour(this.date,j);n=this.moveHour(this.viewDate,j)}else{if(m===0){i=this.moveMinute(this.date,j);n=this.moveMinute(this.viewDate,j)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 38:case 40:if(!this.keyboardNavigation){break}j=o.keyCode===38?-1:1;m=this.viewMode;if(o.ctrlKey){m+=2}else{if(o.shiftKey){m+=1}}if(m===4){i=this.moveYear(this.date,j);n=this.moveYear(this.viewDate,j)}else{if(m===3){i=this.moveMonth(this.date,j);n=this.moveMonth(this.viewDate,j)}else{if(m===2){i=this.moveDate(this.date,j*7);n=this.moveDate(this.viewDate,j*7)}else{if(m===1){if(this.showMeridian){i=this.moveHour(this.date,j*6);n=this.moveHour(this.viewDate,j*6)}else{i=this.moveHour(this.date,j*4);n=this.moveHour(this.viewDate,j*4)}}else{if(m===0){i=this.moveMinute(this.date,j*4);n=this.moveMinute(this.viewDate,j*4)}}}}}if(this.dateWithinRange(i)){this.date=i;this.viewDate=n;this.setValue();this.update();o.preventDefault();k=true}break;case 13:if(this.viewMode!==0){var p=this.viewMode;this.showMode(-1);this.fill();if(p===this.viewMode&&this.autoclose){this.hide()}}else{this.fill();if(this.autoclose){this.hide()}}o.preventDefault();break;case 9:this.hide();break}if(k){var l;if(this.isInput){l=this.element}else{if(this.component){l=this.element.find("input")}}if(l){l.change()}this.element.trigger({type:"changeDate",date:this.getDate()})}},showMode:function(i){if(i){var j=Math.max(0,Math.min(c.modes.length-1,this.viewMode+i));if(j>=this.minView&&j<=this.maxView){this.element.trigger({type:"changeMode",date:this.viewDate,oldViewMode:this.viewMode,newViewMode:j});this.viewMode=j}}this.picker.find(">div").hide().filter(".datetimepicker-"+c.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()},reset:function(){this._setDate(null,"date")},convertViewModeText:function(i){switch(i){case 4:return"decade";case 3:return"year";case 2:return"month";case 1:return"day";case 0:return"hour"}}};var b=d.fn.datetimepicker;d.fn.datetimepicker=function(k){var i=Array.apply(null,arguments);i.shift();var j;this.each(function(){var n=d(this),m=n.data("datetimepicker"),l=typeof k==="object"&&k;if(!m){n.data("datetimepicker",(m=new g(this,d.extend({},d.fn.datetimepicker.defaults,l))))}if(typeof k==="string"&&typeof m[k]==="function"){j=m[k].apply(m,i);if(j!==f){return false}}});if(j!==f){return j}else{return this}};d.fn.datetimepicker.defaults={};d.fn.datetimepicker.Constructor=g;var e=d.fn.datetimepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],meridiem:["am","pm"],suffix:["st","nd","rd","th"],today:"Today",clear:"Clear"}};var c={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(i){return(((i%4===0)&&(i%100!==0))||(i%400===0))},getDaysInMonth:function(i,j){return[31,(c.isLeapYear(i)?29:28),31,30,31,30,31,31,30,31,30,31][j]},getDefaultFormat:function(i,j){if(i==="standard"){if(j==="input"){return"yyyy-mm-dd hh:ii"}else{return"yyyy-mm-dd hh:ii:ss"}}else{if(i==="php"){if(j==="input"){return"Y-m-d H:i"}else{return"Y-m-d H:i:s"}}else{throw new Error("Invalid format type.")}}},validParts:function(i){if(i==="standard"){return/t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g}else{if(i==="php"){return/[dDjlNwzFmMnStyYaABgGhHis]/g}else{throw new Error("Invalid format type.")}}},nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\rTZ]+/g,parseFormat:function(l,j){var i=l.replace(this.validParts(j),"\0").split("\0"),k=l.match(this.validParts(j));if(!i||!i.length||!k||k.length===0){throw new Error("Invalid date format.")}return{separators:i,parts:k}},parseDate:function(A,y,v,j,r){if(A instanceof Date){var u=new Date(A.valueOf()-A.getTimezoneOffset()*60000);u.setMilliseconds(0);return u}if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii",j)}if(/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(A)){y=this.parseFormat("yyyy-mm-dd hh:ii:ss",j)}if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(A)){var l=/([-+]\d+)([dmwy])/,q=A.match(/([-+]\d+)([dmwy])/g),t,p;A=new Date();for(var x=0;x<q.length;x++){t=l.exec(q[x]);p=parseInt(t[1]);switch(t[2]){case"d":A.setUTCDate(A.getUTCDate()+p);break;case"m":A=g.prototype.moveMonth.call(g.prototype,A,p);break;case"w":A.setUTCDate(A.getUTCDate()+p*7);break;case"y":A=g.prototype.moveYear.call(g.prototype,A,p);break}}return h(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate(),A.getUTCHours(),A.getUTCMinutes(),A.getUTCSeconds(),0)}var q=A&&A.toString().match(this.nonpunctuation)||[],A=new Date(0,0,0,0,0,0,0),m={},z=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","D","DD","d","dd","H","HH","p","P","z","Z"],o={hh:function(s,i){return s.setUTCHours(i)},h:function(s,i){return s.setUTCHours(i)},HH:function(s,i){return s.setUTCHours(i===12?0:i)},H:function(s,i){return s.setUTCHours(i===12?0:i)},ii:function(s,i){return s.setUTCMinutes(i)},i:function(s,i){return s.setUTCMinutes(i)},ss:function(s,i){return s.setUTCSeconds(i)},s:function(s,i){return s.setUTCSeconds(i)},yyyy:function(s,i){return s.setUTCFullYear(i)},yy:function(s,i){return s.setUTCFullYear(2000+i)},m:function(s,i){i-=1;while(i<0){i+=12}i%=12;s.setUTCMonth(i);while(s.getUTCMonth()!==i){if(isNaN(s.getUTCMonth())){return s}else{s.setUTCDate(s.getUTCDate()-1)}}return s},d:function(s,i){return s.setUTCDate(i)},p:function(s,i){return s.setUTCHours(i===1?s.getUTCHours()+12:s.getUTCHours())},z:function(){return r}},B,k,t;o.M=o.MM=o.mm=o.m;o.dd=o.d;o.P=o.p;o.Z=o.z;A=h(A.getFullYear(),A.getMonth(),A.getDate(),A.getHours(),A.getMinutes(),A.getSeconds());if(q.length===y.parts.length){for(var x=0,w=y.parts.length;x<w;x++){B=parseInt(q[x],10);
15737t=y.parts[x];if(isNaN(B)){switch(t){case"MM":k=d(e[v].months).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i===s});B=d.inArray(k[0],e[v].months)+1;break;case"M":k=d(e[v].monthsShort).filter(function(){var i=this.slice(0,q[x].length),s=q[x].slice(0,i.length);return i.toLowerCase()===s.toLowerCase()});B=d.inArray(k[0],e[v].monthsShort)+1;break;case"p":case"P":B=d.inArray(q[x].toLowerCase(),e[v].meridiem);break;case"z":case"Z":r;break}}m[t]=B}for(var x=0,n;x<z.length;x++){n=z[x];if(n in m&&!isNaN(m[n])){o[n](A,m[n])}}}return A},formatDate:function(l,q,m,p,o){if(l===null){return""}var k;if(p==="standard"){k={t:l.getTime(),yy:l.getUTCFullYear().toString().substring(2),yyyy:l.getUTCFullYear(),m:l.getUTCMonth()+1,M:e[m].monthsShort[l.getUTCMonth()],MM:e[m].months[l.getUTCMonth()],d:l.getUTCDate(),D:e[m].daysShort[l.getUTCDay()],DD:e[m].days[l.getUTCDay()],p:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),h:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds(),z:o};if(e[m].meridiem.length===2){k.H=(k.h%12===0?12:k.h%12)}else{k.H=k.h}k.HH=(k.H<10?"0":"")+k.H;k.P=k.p.toUpperCase();k.Z=k.z;k.hh=(k.h<10?"0":"")+k.h;k.ii=(k.i<10?"0":"")+k.i;k.ss=(k.s<10?"0":"")+k.s;k.dd=(k.d<10?"0":"")+k.d;k.mm=(k.m<10?"0":"")+k.m}else{if(p==="php"){k={y:l.getUTCFullYear().toString().substring(2),Y:l.getUTCFullYear(),F:e[m].months[l.getUTCMonth()],M:e[m].monthsShort[l.getUTCMonth()],n:l.getUTCMonth()+1,t:c.getDaysInMonth(l.getUTCFullYear(),l.getUTCMonth()),j:l.getUTCDate(),l:e[m].days[l.getUTCDay()],D:e[m].daysShort[l.getUTCDay()],w:l.getUTCDay(),N:(l.getUTCDay()===0?7:l.getUTCDay()),S:(l.getUTCDate()%10<=e[m].suffix.length?e[m].suffix[l.getUTCDate()%10-1]:""),a:(e[m].meridiem.length===2?e[m].meridiem[l.getUTCHours()<12?0:1]:""),g:(l.getUTCHours()%12===0?12:l.getUTCHours()%12),G:l.getUTCHours(),i:l.getUTCMinutes(),s:l.getUTCSeconds()};k.m=(k.n<10?"0":"")+k.n;k.d=(k.j<10?"0":"")+k.j;k.A=k.a.toString().toUpperCase();k.h=(k.g<10?"0":"")+k.g;k.H=(k.G<10?"0":"")+k.G;k.i=(k.i<10?"0":"")+k.i;k.s=(k.s<10?"0":"")+k.s}else{throw new Error("Invalid format type.")}}var l=[],r=d.extend([],q.separators);for(var n=0,j=q.parts.length;n<j;n++){if(r.length){l.push(r.shift())}l.push(k[q.parts[n]])}if(r.length){l.push(r.shift())}return l.join("")},convertViewMode:function(i){switch(i){case 4:case"decade":i=4;break;case 3:case"year":i=3;break;case 2:case"month":i=2;break;case 1:case"day":i=1;break;case 0:case"hour":i=0;break}return i},headTemplate:'<thead><tr><th class="prev"><i class="{iconType} {leftArrow}"/></th><th colspan="5" class="switch"></th><th class="next"><i class="{iconType} {rightArrow}"/></th></tr></thead>',headTemplateV3:'<thead><tr><th class="prev"><span class="{iconType} {leftArrow}"></span> </th><th colspan="5" class="switch"></th><th class="next"><span class="{iconType} {rightArrow}"></span> </th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};c.template='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplate+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplate+c.contTemplate+c.footTemplate+"</table></div></div>";c.templateV3='<div class="datetimepicker"><div class="datetimepicker-minutes"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-hours"><table class=" table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-days"><table class=" table-condensed">'+c.headTemplateV3+"<tbody></tbody>"+c.footTemplate+'</table></div><div class="datetimepicker-months"><table class="table-condensed">
15737'+c.headTemplateV3+c.contTemplate+c.footTemplate+'</table></div><div class="datetimepicker-years"><table class="table-condensed">'+c.headTemplateV3+c.contTemplate+c.footTemplate+"</table></div></div>";d.fn.datetimepicker.DPGlobal=c;d.fn.datetimepicker.noConflict=function(){d.fn.datetimepicker=b;return this};d(document).on("focus.datetimepicker.data-api click.datetimepicker.data-api",'[data-provide="datetimepicker"]',function(j){var i=d(this);if(i.data("datetimepicker")){return}j.preventDefault();i.datetimepicker("show")});d(function(){d('[data-provide="datetimepicker-inline"]').datetimepicker()})})); 15738/*! bootstrap-timepicker v0.5.2 15739* http://jdewit.github.com/bootstrap-timepicker 15740* Copyright (c) 2016 Joris de Wit and bootstrap-timepicker contributors 15741* MIT License 15742*/!function(a,b,c){"use strict";var d=function(b,c){this.widget="",this.$element=a(b),this.defaultTime=c.defaultTime,this.disableFocus=c.disableFocus,this.disableMousewheel=c.disableMousewheel,this.isOpen=c.isOpen,this.minuteStep=c.minuteStep,this.modalBackdrop=c.modalBackdrop,this.orientation=c.orientation,this.secondStep=c.secondStep,this.snapToStep=c.snapToStep,this.showInputs=c.showInputs,this.showMeridian=c.showMeridian,this.showSeconds=c.showSeconds,this.template=c.template,this.appendWidgetTo=c.appendWidgetTo,this.showWidgetOnAddonClick=c.showWidgetOnAddonClick,this.icons=c.icons,this.maxHours=c.maxHours,this.explicitMode=c.explicitMode,this.handleDocumentClick=function(a){var b=a.data.scope;b.$element.parent().find(a.target).length||b.$widget.is(a.target)||b.$widget.find(a.target).length||b.hideWidget()},this._init()};d.prototype={constructor:d,_init:function(){var b=this;this.showWidgetOnAddonClick&&this.$element.parent().hasClass("input-group")&&this.$element.parent().hasClass("bootstrap-timepicker")?(this.$element.parent(".input-group.bootstrap-timepicker").find(".input-group-addon").on({"click.timepicker":a.proxy(this.showWidget,this)}),this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)})):this.template?this.$element.on({"focus.timepicker":a.proxy(this.showWidget,this),"click.timepicker":a.proxy(this.showWidget,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}):this.$element.on({"focus.timepicker":a.proxy(this.highlightUnit,this),"click.timepicker":a.proxy(this.highlightUnit,this),"keydown.timepicker":a.proxy(this.elementKeydown,this),"blur.timepicker":a.proxy(this.blurElement,this),"mousewheel.timepicker DOMMouseScroll.timepicker":a.proxy(this.mousewheel,this)}),this.template!==!1?this.$widget=a(this.getTemplate()).on("click",a.proxy(this.widgetClick,this)):this.$widget=!1,this.showInputs&&this.$widget!==!1&&this.$widget.find("input").each(function(){a(this).on({"click.timepicker":function(){a(this).select()},"keydown.timepicker":a.proxy(b.widgetKeydown,b),"keyup.timepicker":a.proxy(b.widgetKeyup,b)})}),this.setDefaultTime(this.defaultTime)},blurElement:function(){this.highlightedUnit=null,this.updateFromElementVal()},clear:function(){this.hour="",this.minute="",this.second="",this.meridian="",this.$element.val("")},decrementHour:function(){if(this.showMeridian)if(1===this.hour)this.hour=12;else{if(12===this.hour)return this.hour--,this.toggleMeridian();if(0===this.hour)return this.hour=11,this.toggleMeridian();this.hour--}else this.hour<=0?this.hour=this.maxHours-1:this.hour--},decrementMinute:function(a){var b;b=a?this.minute-a:this.minute-this.minuteStep,0>b?(this.decrementHour(),this.minute=b+60):this.minute=b},decrementSecond:function(){var a=this.second-this.secondStep;0>a?(this.decrementMinute(!0),this.second=a+60):this.second=a},elementKeydown:function(a){switch(a.which){case 9:if(a.shiftKey){if("hour"===this.highlightedUnit){this.hideWidget();break}this.highlightPrevUnit()}else{if(this.showMeridian&&"meridian"===this.highlightedUnit||this.showSeconds&&"second"===this.highlightedUnit||!this.showMeridian&&!this.showSeconds&&"minute"===this.highlightedUnit){this.hideWidget();break}this.highlightNextUnit()}a.preventDefault(),this.updateFromElementVal();break;case 27:this.updateFromElementVal();break;case 37:a.preventDefault(),this.highlightPrevUnit(),this.updateFromElementVal();break;case 38:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.incrementHour(),this.highlightHour();break;case"minute":this.incrementMinute(),this.highlightMinute();break;case"second":this.incrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update();break;case 39:a.preventDefault(),this.highlightNextUnit(),this.updateFromElementVal();break;case 40:switch(a.preventDefault(),this.highlightedUnit){case"hour":this.decrementHour(),this.highlightHour();break;case"minute":this.decrementMinute(),this.highlightMinute();break;case"second":this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian()}this.update()}},getCursorPosition:function(){var a=this.$element.get(0);if("selectionStart"in a)return a.selectionStart;if(c.selection){a.focus();var b=c.selection.createRange(),d=c.selection.createRange().text.length;return b.moveStart("character",-a.value.length),b.text.length-d}},getTemplate:function(){var a,b,c,d,e,f;switch(this.showInputs?(b='<input type="text" class="bootstrap-timepicker-hour" maxlength="2"/>',c='<input type="text" class="bootstrap-timepicker-minute" maxlength="2"/>',d='<input type="text" class="bootstrap-timepicker-second" maxlength="2"/>',e='<input type="text" class="bootstrap-timepicker-meridian" maxlength="2"/>'):(b='<span class="bootstrap-timepicker-hour"></span>',c='<span class="bootstrap-timepicker-minute"></span>',d='<span class="bootstrap-timepicker-second"></span>',e='<span class="bootstrap-timepicker-meridian"></span>'),f='<table><tr><td><a href="#" data-action="incrementHour"><span class="'+this.icons.up+'"></span></a></td><td class="separator"> </td><td><a href="#" data-action="incrementMinute"><span class="'+this.icons.up+'"></span></a></td>'+(this.showSeconds?'<td class="separator"> </td><td><a href="#" data-action="incrementSecond"><span class="'+this.icons.up+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator"> </td><td class="meridian-column"><a href="#" data-action="toggleMeridian"><span class="'+this.icons.up+'"></span></a></td>':"")+"</tr><tr><td>"+b+'</td> <td class="separator">:</td><td>'+c+"</td> "+(this.showSeconds?'<td class="separator">:</td><td>'+d+"</td>":"")+(this.showMeridian?'<td class="separator"> </td><td>'+e+"</td>":"")+'</tr><tr><td><a href="#" data-action="decrementHour"><span class="'+this.icons.down+'"></span></a></td><td class="separator"></td><td><a href="#" data-action="decrementMinute"><span class="'+this.icons.down+'"></span></a></td>'+(this.showSeconds?'<td class="separator"> </td><td><a href="#" data-action="decrementSecond"><span class="'+this.icons.down+'"></span></a></td>':"")+(this.showMeridian?'<td class="separator"> </td><td><a href="#" data-action="toggleMeridian"><span class="'+this.icons.down+'"></span></a></td>':"")+"</tr></table>",this.template){case"modal":a='<div class="bootstrap-timepicker-widget modal hide fade in" data-backdrop="'+(this.modalBackdrop?"true":"false")+'"><div class="modal-header"><a href="#" class="close" data-dismiss="modal">×</a><h3>
15742Pick a Time</h3></div><div class="modal-content">'+f+'</div><div class="modal-footer"><a href="#" class="btn btn-primary" data-dismiss="modal">OK</a></div></div>';break;case"dropdown":a='<div class="bootstrap-timepicker-widget dropdown-menu">'+f+"</div>"}return a},getTime:function(){return""===this.hour?"":this.hour+":"+(1===this.minute.toString().length?"0"+this.minute:this.minute)+(this.showSeconds?":"+(1===this.second.toString().length?"0"+this.second:this.second):"")+(this.showMeridian?" "+this.meridian:"")},hideWidget:function(){this.isOpen!==!1&&(this.$element.trigger({type:"hide.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),"modal"===this.template&&this.$widget.modal?this.$widget.modal("hide"):this.$widget.removeClass("open"),a(c).off("mousedown.timepicker, touchend.timepicker",this.handleDocumentClick),this.isOpen=!1,this.$widget.detach())},highlightUnit:function(){this.position=this.getCursorPosition(),this.position>=0&&this.position<=2?this.highlightHour():this.position>=3&&this.position<=5?this.highlightMinute():this.position>=6&&this.position<=8?this.showSeconds?this.highlightSecond():this.highlightMeridian():this.position>=9&&this.position<=11&&this.highlightMeridian()},highlightNextUnit:function(){switch(this.highlightedUnit){case"hour":this.highlightMinute();break;case"minute":this.showSeconds?this.highlightSecond():this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"second":this.showMeridian?this.highlightMeridian():this.highlightHour();break;case"meridian":this.highlightHour()}},highlightPrevUnit:function(){switch(this.highlightedUnit){case"hour":this.showMeridian?this.highlightMeridian():this.showSeconds?this.highlightSecond():this.highlightMinute();break;case"minute":this.highlightHour();break;case"second":this.highlightMinute();break;case"meridian":this.showSeconds?this.highlightSecond():this.highlightMinute()}},highlightHour:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="hour",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(0,1):a.setSelectionRange(0,2)},0)},highlightMinute:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="minute",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(2,4):a.setSelectionRange(3,5)},0)},highlightSecond:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="second",a.setSelectionRange&&setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0)},highlightMeridian:function(){var a=this.$element.get(0),b=this;this.highlightedUnit="meridian",a.setSelectionRange&&(this.showSeconds?setTimeout(function(){b.hour<10?a.setSelectionRange(8,10):a.setSelectionRange(9,11)},0):setTimeout(function(){b.hour<10?a.setSelectionRange(5,7):a.setSelectionRange(6,8)},0))},incrementHour:function(){if(this.showMeridian){if(11===this.hour)return this.hour++,this.toggleMeridian();12===this.hour&&(this.hour=0)}return this.hour===this.maxHours-1?void(this.hour=0):void this.hour++},incrementMinute:function(a){var b;b=a?this.minute+a:this.minute+this.minuteStep-this.minute%this.minuteStep,b>59?(this.incrementHour(),this.minute=b-60):this.minute=b},incrementSecond:function(){var a=this.second+this.secondStep-this.second%this.secondStep;a>59?(this.incrementMinute(!0),this.second=a-60):this.second=a},mousewheel:function(b){if(!this.disableMousewheel){b.preventDefault(),b.stopPropagation();var c=b.originalEvent.wheelDelta||-b.originalEvent.detail,d=null;switch("mousewheel"===b.type?d=-1*b.originalEvent.wheelDelta:"DOMMouseScroll"===b.type&&(d=40*b.originalEvent.detail),d&&(b.preventDefault(),a(this).scrollTop(d+a(this).scrollTop())),this.highlightedUnit){case"minute":c>0?this.incrementMinute():this.decrementMinute(),this.highlightMinute();break;case"second":c>0?this.incrementSecond():this.decrementSecond(),this.highlightSecond();break;case"meridian":this.toggleMeridian(),this.highlightMeridian();break;default:c>0?this.incrementHour():this.decrementHour(),this.highlightHour()}return!1}},changeToNearestStep:function(a,b){return a%b===0?a:Math.round(a%b/b)?(a+(b-a%b))%60:a-a%b},place:function(){if(!this.isInline){var c=this.$widget.outerWidth(),d=this.$widget.outerHeight(),e=10,f=a(b).width(),g=a(b).height(),h=a(b).scrollTop(),i=parseInt(this.$element.parents().filter(function(){return"auto"!==a(this).css("z-index")}).first().css("z-index"),10)+10,j=this.component?this.component.parent().offset():this.$element.offset(),k=this.component?this.component.outerHeight(!0):this.$element.outerHeight(!1),l=this.component?this.component.outerWidth(!0):this.$element.outerWidth(!1),m=j.left,n=j.top;this.$widget.removeClass("timepicker-orient-top timepicker-orient-bottom timepicker-orient-right timepicker-orient-left"),"auto"!==this.orientation.x?(this.$widget.addClass("timepicker-orient-"+this.orientation.x),"right"===this.orientation.x&&(m-=c-l)):(this.$widget.addClass("timepicker-orient-left"),j.left<0?m-=j.left-e:j.left+c>f&&(m=f-c-e));var o,p,q=this.orientation.y;"auto"===q&&(o=-h+j.top-d,p=h+g-(j.top+k+d),q=Math.max(o,p)===p?"top":"bottom"),this.$widget.addClass("timepicker-orient-"+q),"top"===q?n+=k:n-=d+
15742parseInt(this.$widget.css("padding-top"),10),this.$widget.css({top:n,left:m,zIndex:i})}},remove:function(){a("document").off(".timepicker"),this.$widget&&this.$widget.remove(),delete this.$element.data().timepicker},setDefaultTime:function(a){if(this.$element.val())this.updateFromElementVal();else if("current"===a){var b=new Date,c=b.getHours(),d=b.getMinutes(),e=b.getSeconds(),f="AM";0!==e&&(e=Math.ceil(b.getSeconds()/this.secondStep)*this.secondStep,60===e&&(d+=1,e=0)),0!==d&&(d=Math.ceil(b.getMinutes()/this.minuteStep)*this.minuteStep,60===d&&(c+=1,d=0)),this.showMeridian&&(0===c?c=12:c>=12?(c>12&&(c-=12),f="PM"):f="AM"),this.hour=c,this.minute=d,this.second=e,this.meridian=f,this.update()}else a===!1?(this.hour=0,this.minute=0,this.second=0,this.meridian="AM"):this.setTime(a)},setTime:function(a,b){if(!a)return void this.clear();var c,d,e,f,g,h;if("object"==typeof a&&a.getMonth)e=a.getHours(),f=a.getMinutes(),g=a.getSeconds(),this.showMeridian&&(h="AM",e>12&&(h="PM",e%=12),12===e&&(h="PM"));else{if(c=(/a/i.test(a)?1:0)+(/p/i.test(a)?2:0),c>2)return void this.clear();if(d=a.replace(/[^0-9\:]/g,"").split(":"),e=d[0]?d[0].toString():d.toString(),this.explicitMode&&e.length>2&&e.length%2!==0)return void this.clear();f=d[1]?d[1].toString():"",g=d[2]?d[2].toString():"",e.length>4&&(g=e.slice(-2),e=e.slice(0,-2)),e.length>2&&(f=e.slice(-2),e=e.slice(0,-2)),f.length>2&&(g=f.slice(-2),f=f.slice(0,-2)),e=parseInt(e,10),f=parseInt(f,10),g=parseInt(g,10),isNaN(e)&&(e=0),isNaN(f)&&(f=0),isNaN(g)&&(g=0),g>59&&(g=59),f>59&&(f=59),e>=this.maxHours&&(e=this.maxHours-1),this.showMeridian?(e>12&&(c=2,e-=12),c||(c=1),0===e&&(e=12),h=1===c?"AM":"PM"):12>e&&2===c?e+=12:e>=this.maxHours?e=this.maxHours-1:(0>e||12===e&&1===c)&&(e=0)}this.hour=e,this.snapToStep?(this.minute=this.changeToNearestStep(f,this.minuteStep),this.second=this.changeToNearestStep(g,this.secondStep)):(this.minute=f,this.second=g),this.meridian=h,this.update(b)},showWidget:function(){this.isOpen||this.$element.is(":disabled")||(this.$widget.appendTo(this.appendWidgetTo),a(c).on("mousedown.timepicker, touchend.timepicker",{scope:this},this.handleDocumentClick),this.$element.trigger({type:"show.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}}),this.place(),this.disableFocus&&this.$element.blur(),""===this.hour&&(this.defaultTime?this.setDefaultTime(this.defaultTime):this.setTime("0:0:0")),"modal"===this.template&&this.$widget.modal?this.$widget.modal("show").on("hidden",a.proxy(this.hideWidget,this)):this.isOpen===!1&&this.$widget.addClass("open"),this.isOpen=!0)},toggleMeridian:function(){this.meridian="AM"===this.meridian?"PM":"AM"},update:function(a){this.updateElement(),a||this.updateWidget(),this.$element.trigger({type:"changeTime.timepicker",time:{value:this.getTime(),hours:this.hour,minutes:this.minute,seconds:this.second,meridian:this.meridian}})},updateElement:function(){this.$element.val(this.getTime()).change()},updateFromElementVal:function(){this.setTime(this.$element.val())},updateWidget:function(){if(this.$widget!==!1){var a=this.hour,b=1===this.minute.toString().length?"0"+this.minute:this.minute,c=1===this.second.toString().length?"0"+this.second:this.second;this.showInputs?(this.$widget.find("input.bootstrap-timepicker-hour").val(a),this.$widget.find("input.bootstrap-timepicker-minute").val(b),this.showSeconds&&this.$widget.find("input.bootstrap-timepicker-second").val(c),this.showMeridian&&this.$widget.find("input.bootstrap-timepicker-meridian").val(this.meridian)):(this.$widget.find("span.bootstrap-timepicker-hour").text(a),this.$widget.find("span.bootstrap-timepicker-minute").text(b),this.showSeconds&&this.$widget.find("span.bootstrap-timepicker-second").text(c),this.showMeridian&&this.$widget.find("span.bootstrap-timepicker-meridian").text(this.meridian))}},updateFromWidgetInputs:function(){if(this.$widget!==!1){var a=this.$widget.find("input.bootstrap-timepicker-hour").val()+":"+this.$widget.find("input.bootstrap-timepicker-minute").val()+(this.showSeconds?":"+this.$widget.find("input.bootstrap-timepicker-second").val():"")+(this.showMeridian?this.$widget.find("input.bootstrap-timepicker-meridian").val():"");this.setTime(a,!0)}},widgetClick:function(b){b.stopPropagation(),b.preventDefault();var c=a(b.target),d=c.closest("a").data("action");d&&this[d](),this.update(),c.is("input")&&c.get(0).setSelectionRange(0,2)},widgetKeydown:function(b){var c=a(b.target),d=c.attr("class").replace("bootstrap-timepicker-","");
15742switch(b.which){case 9:if(b.shiftKey){if("hour"===d)return this.hideWidget()}else if(this.showMeridian&&"meridian"===d||this.showSeconds&&"second"===d||!this.showMeridian&&!this.showSeconds&&"minute"===d)return this.hideWidget();break;case 27:this.hideWidget();break;case 38:switch(b.preventDefault(),d){case"hour":this.incrementHour();break;case"minute":this.incrementMinute();break;case"second":this.incrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2);break;case 40:switch(b.preventDefault(),d){case"hour":this.decrementHour();break;case"minute":this.decrementMinute();break;case"second":this.decrementSecond();break;case"meridian":this.toggleMeridian()}this.setTime(this.getTime()),c.get(0).setSelectionRange(0,2)}},widgetKeyup:function(a){(65===a.which||77===a.which||80===a.which||46===a.which||8===a.which||a.which>=48&&a.which<=57||a.which>=96&&a.which<=105)&&this.updateFromWidgetInputs()}},a.fn.timepicker=function(b){var c=Array.apply(null,arguments);return c.shift(),this.each(function(){var e=a(this),f=e.data("timepicker"),g="object"==typeof b&&b;f||e.data("timepicker",f=new d(this,a.extend({},a.fn.timepicker.defaults,g,a(this).data()))),"string"==typeof b&&f[b].apply(f,c)})},a.fn.timepicker.defaults={defaultTime:"current",disableFocus:!1,disableMousewheel:!1,isOpen:!1,minuteStep:15,modalBackdrop:!1,orientation:{x:"auto",y:"auto"},secondStep:15,snapToStep:!1,showSeconds:!1,showInputs:!0,showMeridian:!0,template:"dropdown",appendWidgetTo:"body",showWidgetOnAddonClick:!0,icons:{up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down"},maxHours:24,explicitMode:!1},a.fn.timepicker.Constructor=d,a(c).on("focus.timepicker.data-api click.timepicker.data-api",'[data-provide="timepicker"]',function(b){var c=a(this);c.data("timepicker")||(b.preventDefault(),c.timepicker())})}(jQuery,window,document); 15743"use strict"; 15744$.fn.timepicker.defaults = $.extend(true, {}, $.fn.timepicker.defaults, { 15745 icons: { 15746 up: 'la la-angle-up', 15747 down: 'la la-angle-down' 15748 } 15749}); 15750/** 15751* @version: 3.0.5 15752* @author: Dan Grossman http://www.dangrossman.info/ 15753* @copyright: Copyright (c) 2012-2019 Dan Grossman. All rights reserved. 15754* @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php 15755* @website: http://www.daterangepicker.com/ 15756*/ 15757// Following the UMD template https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js 15758(function (root, factory) { 15759 if (typeof define === 'function' && define.amd) { 15760 // AMD. Make globaly available as well 15761 define(['moment', 'jquery'], function (moment, jquery) { 15762 if (!jquery.fn) jquery.fn = {}; // webpack server rendering 15763 if (typeof moment !== 'function' && moment.default) moment = moment.default 15764 return factory(moment, jquery); 15765 }); 15766 } else if (typeof module === 'object' && module.exports) { 15767 // Node / Browserify 15768 //isomorphic issue 15769 var jQuery = (typeof window != 'undefined') ? window.jQuery : undefined; 15770 if (!jQuery) { 15771 jQuery = require('jquery'); 15772 if (!jQuery.fn) jQuery.fn = {}; 15773 } 15774 var moment = (typeof window != 'undefined' && typeof window.moment != 'undefined') ? window.moment : require('moment'); 15775 module.exports = factory(moment, jQuery); 15776 } else { 15777 // Browser globals 15778 root.daterangepicker = factory(root.moment, root.jQuery); 15779 } 15780}(this, function(moment, $) { 15781 var DateRangePicker = function(element, options, cb) { 15782 15783 //default settings for options 15784 this.parentEl = 'body'; 15785 this.element = $(element); 15786 this.startDate = moment().startOf('day'); 15787 this.endDate = moment().endOf('day'); 15788 this.minDate = false; 15789 this.maxDate = false; 15790 this.maxSpan = false; 15791 this.autoApply = false; 15792 this.singleDatePicker = false; 15793 this.showDropdowns = false; 15794 this.minYear = moment().subtract(100, 'year').format('YYYY'); 15795 this.maxYear = moment().add(100, 'year').format('YYYY'); 15796 this.showWeekNumbers = false;
vendor: 64,818 bytes, lines 15797-17359
15797 this.showISOWeekNumbers = false; 15798 this.showCustomRangeLabel = true; 15799 this.timePicker = false; 15800 this.timePicker24Hour = false; 15801 this.timePickerIncrement = 1; 15802 this.timePickerSeconds = false; 15803 this.linkedCalendars = true; 15804 this.autoUpdateInput = true; 15805 this.alwaysShowCalendars = false; 15806 this.ranges = {}; 15807 15808 this.opens = 'right'; 15809 if (this.element.hasClass('pull-right')) 15810 this.opens = 'left'; 15811 15812 this.drops = 'down'; 15813 if (this.element.hasClass('dropup')) 15814 this.drops = 'up'; 15815 15816 this.buttonClasses = 'btn btn-sm'; 15817 this.applyButtonClasses = 'btn-primary'; 15818 this.cancelButtonClasses = 'btn-default'; 15819 15820 this.locale = { 15821 direction: 'ltr', 15822 format: moment.localeData().longDateFormat('L'), 15823 separator: ' - ', 15824 applyLabel: 'Apply', 15825 cancelLabel: 'Cancel', 15826 weekLabel: 'W', 15827 customRangeLabel: 'Custom Range', 15828 daysOfWeek: moment.weekdaysMin(), 15829 monthNames: moment.monthsShort(), 15830 firstDay: moment.localeData().firstDayOfWeek() 15831 }; 15832 15833 this.callback = function() { }; 15834 15835 //some state information 15836 this.isShowing = false; 15837 this.leftCalendar = {}; 15838 this.rightCalendar = {}; 15839 15840 //custom options from user 15841 if (typeof options !== 'object' || options === null) 15842 options = {}; 15843 15844 //allow setting options with data attributes 15845 //data-api options will be overwritten with custom javascript options 15846 options = $.extend(this.element.data(), options); 15847 15848 //html template for the picker UI 15849 if (typeof options.template !== 'string' && !(options.template instanceof $)) 15850 options.template = 15851 '<div class="daterangepicker">' + 15852 '<div class="ranges"></div>' + 15853 '<div class="drp-calendar left">' + 15854 '<div class="calendar-table"></div>' + 15855 '<div class="calendar-time"></div>' + 15856 '</div>' + 15857 '<div class="drp-calendar right">' + 15858 '<div class="calendar-table"></div>' + 15859 '<div class="calendar-time"></div>' + 15860 '</div>' + 15861 '<div class="drp-buttons">' + 15862 '<span class="drp-selected"></span>' + 15863 '<button class="cancelBtn" type="button"></button>' + 15864 '<button class="applyBtn" disabled="disabled" type="button"></button> ' + 15865 '</div>' + 15866 '</div>'; 15867 15868 this.parentEl = (options.parentEl && $(options.parentEl).length) ? $(options.parentEl) : $(this.parentEl); 15869 this.container = $(options.template).appendTo(this.parentEl); 15870 15871 // 15872 // handle all the possible options overriding defaults 15873 // 15874 15875 if (typeof options.locale === 'object') { 15876 15877 if (typeof options.locale.direction === 'string') 15878 this.locale.direction = options.locale.direction; 15879 15880 if (typeof options.locale.format === 'string') 15881 this.locale.format = options.locale.format; 15882 15883 if (typeof options.locale.separator === 'string') 15884 this.locale.separator = options.locale.separator; 15885 15886 if (typeof options.locale.daysOfWeek === 'object') 15887 this.locale.daysOfWeek = options.locale.daysOfWeek.slice(); 15888 15889 if (typeof options.locale.monthNames === 'object') 15890 this.locale.monthNames = options.locale.monthNames.slice(); 15891 15892 if (typeof options.locale.firstDay === 'number') 15893 this.locale.firstDay = options.locale.firstDay; 15894 15895 if (typeof options.locale.applyLabel === 'string') 15896 this.locale.applyLabel = options.locale.applyLabel; 15897 15898 if (typeof options.locale.cancelLabel === 'string') 15899 this.locale.cancelLabel = options.locale.cancelLabel; 15900 15901 if (typeof options.locale.weekLabel === 'string') 15902 this.locale.weekLabel = options.locale.weekLabel; 15903 15904 if (typeof options.locale.customRangeLabel === 'string'){ 15905 //Support unicode chars in the custom range name. 15906 var elem = document.createElement('textarea'); 15907 elem.innerHTML = options.locale.customRangeLabel; 15908 var rangeHtml = elem.value; 15909 this.locale.customRangeLabel = rangeHtml; 15910 } 15911 } 15912 this.container.addClass(this.locale.direction); 15913 15914 if (typeof options.startDate === 'string') 15915 this.startDate = moment(options.startDate, this.locale.format); 15916 15917 if (typeof options.endDate === 'string') 15918 this.endDate = moment(options.endDate, this.locale.format); 15919 15920 if (typeof options.minDate === 'string') 15921 this.minDate = moment(options.minDate, this.locale.format); 15922 15923 if (typeof options.maxDate === 'string') 15924 this.maxDate = moment(options.maxDate, this.locale.format); 15925 15926 if (typeof options.startDate === 'object') 15927 this.startDate = moment(options.startDate); 15928 15929 if (typeof options.endDate === 'object') 15930 this.endDate = moment(options.endDate); 15931 15932 if (typeof options.minDate === 'object') 15933 this.minDate = moment(options.minDate); 15934 15935 if (typeof options.maxDate === 'object') 15936 this.maxDate = moment(options.maxDate); 15937 15938 // sanity check for bad options 15939 if (this.minDate && this.startDate.isBefore(this.minDate)) 15940 this.startDate = this.minDate.clone(); 15941 15942 // sanity check for bad options 15943 if (this.maxDate && this.endDate.isAfter(this.maxDate)) 15944 this.endDate = this.maxDate.clone(); 15945 15946 if (typeof options.applyButtonClasses === 'string') 15947 this.applyButtonClasses = options.applyButtonClasses; 15948 15949 if (typeof options.applyClass === 'string') //backwards compat 15950 this.applyButtonClasses = options.applyClass; 15951 15952 if (typeof options.cancelButtonClasses === 'string') 15953 this.cancelButtonClasses = options.cancelButtonClasses; 15954 15955 if (typeof options.cancelClass === 'string') //backwards compat 15956 this.cancelButtonClasses = options.cancelClass; 15957 15958 if (typeof options.maxSpan === 'object') 15959 this.maxSpan = options.maxSpan; 15960 15961 if (typeof options.dateLimit === 'object') //backwards compat 15962 this.maxSpan = options.dateLimit; 15963 15964 if (typeof options.opens === 'string') 15965 this.opens = options.opens; 15966 15967 if (typeof options.drops === 'string') 15968 this.drops = options.drops; 15969 15970 if (typeof options.showWeekNumbers === 'boolean') 15971 this.showWeekNumbers = options.showWeekNumbers; 15972 15973 if (typeof options.showISOWeekNumbers === 'boolean') 15974 this.showISOWeekNumbers = options.showISOWeekNumbers; 15975 15976 if (typeof options.buttonClasses === 'string') 15977 this.buttonClasses = options.buttonClasses; 15978 15979 if (typeof options.buttonClasses === 'object') 15980 this.buttonClasses = options.buttonClasses.join(' '); 15981 15982 if (typeof options.showDropdowns === 'boolean') 15983 this.showDropdowns = options.showDropdowns; 15984 15985 if (typeof options.minYear === 'number') 15986 this.minYear = options.minYear; 15987 15988 if (typeof options.maxYear === 'number') 15989 this.maxYear = options.maxYear; 15990 15991 if (typeof options.showCustomRangeLabel === 'boolean') 15992 this.showCustomRangeLabel = options.showCustomRangeLabel; 15993 15994 if (typeof options.singleDatePicker === 'boolean') { 15995 this.singleDatePicker = options.singleDatePicker; 15996 if (this.singleDatePicker) 15997 this.endDate = this.startDate.clone(); 15998 } 15999 16000 if (typeof options.timePicker === 'boolean') 16001 this.timePicker = options.timePicker; 16002 16003 if (typeof options.timePickerSeconds === 'boolean') 16004 this.timePickerSeconds = options.timePickerSeconds; 16005 16006 if (typeof options.timePickerIncrement === 'number') 16007 this.timePickerIncrement = options.timePickerIncrement; 16008 16009 if (typeof options.timePicker24Hour === 'boolean') 16010 this.timePicker24Hour = options.timePicker24Hour; 16011 16012 if (typeof options.autoApply === 'boolean') 16013 this.autoApply = options.autoApply; 16014 16015 if (typeof options.autoUpdateInput === 'boolean') 16016 this.autoUpdateInput = options.autoUpdateInput; 16017 16018 if (typeof options.linkedCalendars === 'boolean') 16019 this.linkedCalendars = options.linkedCalendars; 16020 16021 if (typeof options.isInvalidDate === 'function') 16022 this.isInvalidDate = options.isInvalidDate; 16023 16024 if (typeof options.isCustomDate === 'function') 16025 this.isCustomDate = options.isCustomDate; 16026 16027 if (typeof options.alwaysShowCalendars === 'boolean') 16028 this.alwaysShowCalendars = options.alwaysShowCalendars; 16029 16030 // update day names order to firstDay 16031 if (this.locale.firstDay != 0) { 16032 var iterator = this.locale.firstDay; 16033 while (iterator > 0) { 16034 this.locale.daysOfWeek.push(this.locale.daysOfWeek.shift()); 16035 iterator--; 16036 } 16037 } 16038 16039 var start, end, range; 16040 16041 //if no start/end dates set, check if an input element contains initial values 16042 if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { 16043 if ($(this.element).is(':text')) { 16044 var val = $(this.element).val(), 16045 split = val.split(this.locale.separator); 16046 16047 start = end = null; 16048 16049 if (split.length == 2) { 16050 start = moment(split[0], this.locale.format); 16051 end = moment(split[1], this.locale.format); 16052 } else if (this.singleDatePicker && val !== "") { 16053 start = moment(val, this.locale.format); 16054 end = moment(val, this.locale.format); 16055 } 16056 if (start !== null && end !== null) { 16057 this.setStartDate(start); 16058 this.setEndDate(end); 16059 } 16060 } 16061 } 16062 16063 if (typeof options.ranges === 'object') { 16064 for (range in options.ranges) { 16065 16066 if (typeof options.ranges[range][0] === 'string') 16067 start = moment(options.ranges[range][0], this.locale.format); 16068 else 16069 start = moment(options.ranges[range][0]); 16070 16071 if (typeof options.ranges[range][1] === 'string') 16072 end = moment(options.ranges[range][1], this.locale.format); 16073 else 16074 end = moment(options.ranges[range][1]); 16075 16076 // If the start or end date exceed those allowed by the minDate or maxSpan 16077 // options, shorten the range to the allowable period. 16078 if (this.minDate && start.isBefore(this.minDate)) 16079 start = this.minDate.clone(); 16080 16081 var maxDate = this.maxDate; 16082 if (this.maxSpan && maxDate && start.clone().add(this.maxSpan).isAfter(maxDate)) 16083 maxDate = start.clone().add(this.maxSpan); 16084 if (maxDate && end.isAfter(maxDate)) 16085 end = maxDate.clone(); 16086 16087 // If the end of the range is before the minimum or the start of the range is 16088 // after the maximum, don't display this range option at all. 16089 if ((this.minDate && end.isBefore(this.minDate, this.timepicker ? 'minute' : 'day')) 16090 || (maxDate && start.isAfter(maxDate, this.timepicker ? 'minute' : 'day'))) 16091 continue; 16092 16093 //Support unicode chars in the range names. 16094 var elem = document.createElement('textarea'); 16095 elem.innerHTML = range; 16096 var rangeHtml = elem.value; 16097 16098 this.ranges[rangeHtml] = [start, end]; 16099 } 16100 16101 var list = '<ul>'; 16102 for (range in this.ranges) { 16103 list += '<li data-range-key="' + range + '">' + range + '</li>'; 16104 } 16105 if (this.showCustomRangeLabel) { 16106 list += '<li data-range-key="' + this.locale.customRangeLabel + '">' + this.locale.customRangeLabel + '</li>'; 16107 } 16108 list += '</ul>'; 16109 this.container.find('.ranges').prepend(list); 16110 } 16111 16112 if (typeof cb === 'function') { 16113 this.callback = cb; 16114 } 16115 16116 if (!this.timePicker) { 16117 this.startDate = this.startDate.startOf('day'); 16118 this.endDate = this.endDate.endOf('day'); 16119 this.container.find('.calendar-time').hide(); 16120 } 16121 16122 //can't be used together for now 16123 if (this.timePicker && this.autoApply) 16124 this.autoApply = false; 16125 16126 if (this.autoApply) { 16127 this.container.addClass('auto-apply'); 16128 } 16129 16130 if (typeof options.ranges === 'object') 16131 this.container.addClass('show-ranges'); 16132 16133 if (this.singleDatePicker) { 16134 this.container.addClass('single'); 16135 this.container.find('.drp-calendar.left').addClass('single'); 16136 this.container.find('.drp-calendar.left').show(); 16137 this.container.find('.drp-calendar.right').hide(); 16138 if (!this.timePicker) { 16139 this.container.addClass('auto-apply'); 16140 } 16141 } 16142 16143 if ((typeof options.ranges === 'undefined' && !this.singleDatePicker) || this.alwaysShowCalendars) { 16144 this.container.addClass('show-calendar'); 16145 } 16146 16147 this.container.addClass('opens' + this.opens); 16148 16149 //apply CSS classes and labels to buttons 16150 this.container.find('.applyBtn, .cancelBtn').addClass(this.buttonClasses); 16151 if (this.applyButtonClasses.length) 16152 this.container.find('.applyBtn').addClass(this.applyButtonClasses); 16153 if (this.cancelButtonClasses.length) 16154 this.container.find('.cancelBtn').addClass(this.cancelButtonClasses); 16155 this.container.find('.applyBtn').html(this.locale.applyLabel); 16156 this.container.find('.cancelBtn').html(this.locale.cancelLabel); 16157 16158 // 16159 // event listeners 16160 // 16161 16162 this.container.find('.drp-calendar') 16163 .on('click.daterangepicker', '.prev', $.proxy(this.clickPrev, this)) 16164 .on('click.daterangepicker', '.next', $.proxy(this.clickNext, this)) 16165 .on('mousedown.daterangepicker', 'td.available', $.proxy(this.clickDate, this)) 16166 .on('mouseenter.daterangepicker', 'td.available', $.proxy(this.hoverDate, this)) 16167 .on('change.daterangepicker', 'select.yearselect', $.proxy(this.monthOrYearChanged, this)) 16168 .on('change.daterangepicker', 'select.monthselect', $.proxy(this.monthOrYearChanged, this)) 16169 .on('change.daterangepicker', 'select.hourselect,select.minuteselect,select.secondselect,select.ampmselect', $.proxy(this.timeChanged, this)) 16170 16171 this.container.find('.ranges') 16172 .on('click.daterangepicker', 'li', $.proxy(this.clickRange, this)) 16173 16174 this.container.find('.drp-buttons') 16175 .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) 16176 .on('click.daterangepicker', 'button.cancelBtn', $.proxy(this.clickCancel, this)) 16177 16178 if (this.element.is('input') || this.element.is('button')) { 16179 this.element.on({ 16180 'click.daterangepicker': $.proxy(this.show, this), 16181 'focus.daterangepicker': $.proxy(this.show, this), 16182 'keyup.daterangepicker': $.proxy(this.elementChanged, this), 16183 'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility 16184 }); 16185 } else { 16186 this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); 16187 this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this)); 16188 } 16189 16190 // 16191 // if attached to a text input, set the initial value 16192 // 16193 16194 this.updateElement(); 16195 16196 }; 16197 16198 DateRangePicker.prototype = { 16199 16200 constructor: DateRangePicker, 16201 16202 setStartDate: function(startDate) { 16203 if (typeof startDate === 'string') 16204 this.startDate = moment(startDate, this.locale.format); 16205 16206 if (typeof startDate === 'object') 16207 this.startDate = moment(startDate); 16208 16209 if (!this.timePicker) 16210 this.startDate = this.startDate.startOf('day'); 16211 16212 if (this.timePicker && this.timePickerIncrement) 16213 this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 16214 16215 if (this.minDate && this.startDate.isBefore(this.minDate)) { 16216 this.startDate = this.minDate.clone(); 16217 if (this.timePicker && this.timePickerIncrement) 16218 this.startDate.minute(Math.round(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 16219 } 16220 16221 if (this.maxDate && this.startDate.isAfter(this.maxDate)) { 16222 this.startDate = this.maxDate.clone(); 16223 if (this.timePicker && this.timePickerIncrement) 16224 this.startDate.minute(Math.floor(this.startDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 16225 } 16226 16227 if (!this.isShowing) 16228 this.updateElement(); 16229 16230 this.updateMonthsInView(); 16231 }, 16232 16233 setEndDate: function(endDate) { 16234 if (typeof endDate === 'string') 16235 this.endDate = moment(endDate, this.locale.format); 16236 16237 if (typeof endDate === 'object') 16238 this.endDate = moment(endDate); 16239 16240 if (!this.timePicker) 16241 this.endDate = this.endDate.endOf('day'); 16242 16243 if (this.timePicker && this.timePickerIncrement) 16244 this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); 16245 16246 if (this.endDate.isBefore(this.startDate)) 16247 this.endDate = this.startDate.clone(); 16248 16249 if (this.maxDate && this.endDate.isAfter(this.maxDate)) 16250 this.endDate = this.maxDate.clone(); 16251 16252 if (this.maxSpan && this.startDate.clone().add(this.maxSpan).isBefore(this.endDate)) 16253 this.endDate = this.startDate.clone().add(this.maxSpan); 16254 16255 this.previousRightTime = this.endDate.clone(); 16256 16257 this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 16258 16259 if (!this.isShowing) 16260 this.updateElement(); 16261 16262 this.updateMonthsInView(); 16263 }, 16264 16265 isInvalidDate: function() { 16266 return false; 16267 }, 16268 16269 isCustomDate: function() { 16270 return false; 16271 }, 16272 16273 updateView: function() { 16274 if (this.timePicker) { 16275 this.renderTimePicker('left'); 16276 this.renderTimePicker('right'); 16277 if (!this.endDate) { 16278 this.container.find('.right .calendar-time select').attr('disabled', 'disabled').addClass('disabled'); 16279 } else { 16280 this.container.find('.right .calendar-time select').removeAttr('disabled').removeClass('disabled'); 16281 } 16282 } 16283 if (this.endDate) 16284 this.container.find('.drp-selected').html(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); 16285 this.updateMonthsInView(); 16286 this.updateCalendars(); 16287 this.updateFormInputs(); 16288 }, 16289 16290 updateMonthsInView: function() { 16291 if (this.endDate) { 16292 16293 //if both dates are visible already, do nothing 16294 if (!this.singleDatePicker && this.leftCalendar.month && this.rightCalendar.month && 16295 (this.startDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.startDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) 16296 && 16297 (this.endDate.format('YYYY-MM') == this.leftCalendar.month.format('YYYY-MM') || this.endDate.format('YYYY-MM') == this.rightCalendar.month.format('YYYY-MM')) 16298 ) { 16299 return; 16300 } 16301 16302 this.leftCalendar.month = this.startDate.clone().date(2); 16303 if (!this.linkedCalendars && (this.endDate.month() != this.startDate.month() || this.endDate.year() != this.startDate.year())) { 16304 this.rightCalendar.month = this.endDate.clone().date(2); 16305 } else { 16306 this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); 16307 } 16308 16309 } else { 16310 if (this.leftCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM') && this.rightCalendar.month.format('YYYY-MM') != this.startDate.format('YYYY-MM')) { 16311 this.leftCalendar.month = this.startDate.clone().date(2); 16312 this.rightCalendar.month = this.startDate.clone().date(2).add(1, 'month'); 16313 } 16314 } 16315 if (this.maxDate && this.linkedCalendars && !this.singleDatePicker && this.rightCalendar.month > this.maxDate) { 16316 this.rightCalendar.month = this.maxDate.clone().date(2); 16317 this.leftCalendar.month = this.maxDate.clone().date(2).subtract(1, 'month'); 16318 } 16319 }, 16320 16321 updateCalendars: function() { 16322 16323 if (this.timePicker) { 16324 var hour, minute, second; 16325 if (this.endDate) { 16326 hour = parseInt(this.container.find('.left .hourselect').val(), 10); 16327 minute = parseInt(this.container.find('.left .minuteselect').val(), 10); 16328 if (isNaN(minute)) { 16329 minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10); 16330 } 16331 second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; 16332 if (!this.timePicker24Hour) { 16333 var ampm = this.container.find('.left .ampmselect').val(); 16334 if (ampm === 'PM' && hour < 12) 16335 hour += 12; 16336 if (ampm === 'AM' && hour === 12) 16337 hour = 0; 16338 } 16339 } else { 16340 hour = parseInt(this.container.find('.right .hourselect').val(), 10); 16341 minute = parseInt(this.container.find('.right .minuteselect').val(), 10); 16342 if (isNaN(minute)) { 16343 minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10); 16344 } 16345 second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; 16346 if (!this.timePicker24Hour) { 16347 var ampm = this.container.find('.right .ampmselect').val(); 16348 if (ampm === 'PM' && hour < 12) 16349 hour += 12; 16350 if (ampm === 'AM' && hour === 12) 16351 hour = 0; 16352 } 16353 } 16354 this.leftCalendar.month.hour(hour).minute(minute).second(second); 16355 this.rightCalendar.month.hour(hour).minute(minute).second(second); 16356 } 16357 16358 this.renderCalendar('left'); 16359 this.renderCalendar('right'); 16360 16361 //highlight any predefined range matching the current start and end dates 16362 this.container.find('.ranges li').removeClass('active'); 16363 if (this.endDate == null) return; 16364 16365 this.calculateChosenLabel(); 16366 }, 16367 16368 renderCalendar: function(side) { 16369 16370 // 16371 // Build the matrix of dates that will populate the calendar 16372 // 16373 16374 var calendar = side == 'left' ? this.leftCalendar : this.rightCalendar; 16375 var month = calendar.month.month(); 16376 var year = calendar.month.year(); 16377 var hour = calendar.month.hour(); 16378 var minute = calendar.month.minute(); 16379 var second = calendar.month.second(); 16380 var daysInMonth = moment([year, month]).daysInMonth(); 16381 var firstDay = moment([year, month, 1]); 16382 var lastDay = moment([year, month, daysInMonth]); 16383 var lastMonth = moment(firstDay).subtract(1, 'month').month(); 16384 var lastYear = moment(firstDay).subtract(1, 'month').year(); 16385 var daysInLastMonth = moment([lastYear, lastMonth]).daysInMonth(); 16386 var dayOfWeek = firstDay.day(); 16387 16388 //initialize a 6 rows x 7 columns array for the calendar 16389 var calendar = []; 16390 calendar.firstDay = firstDay; 16391 calendar.lastDay = lastDay; 16392 16393 for (var i = 0; i < 6; i++) { 16394 calendar[i] = []; 16395 } 16396 16397 //populate the calendar with date objects 16398 var startDay = daysInLastMonth - dayOfWeek + this.locale.firstDay + 1; 16399 if (startDay > daysInLastMonth) 16400 startDay -= 7; 16401 16402 if (dayOfWeek == this.locale.firstDay) 16403 startDay = daysInLastMonth - 6; 16404 16405 var curDate = moment([lastYear, lastMonth, startDay, 12, minute, second]); 16406 16407 var col, row; 16408 for (var i = 0, col = 0, row = 0; i < 42; i++, col++, curDate = moment(curDate).add(24, 'hour')) { 16409 if (i > 0 && col % 7 === 0) { 16410 col = 0; 16411 row++; 16412 } 16413 calendar[row][col] = curDate.clone().hour(hour).minute(minute).second(second); 16414 curDate.hour(12); 16415 16416 if (this.minDate && calendar[row][col].format('YYYY-MM-DD') == this.minDate.format('YYYY-MM-DD') && calendar[row][col].isBefore(this.minDate) && side == 'left') { 16417 calendar[row][col] = this.minDate.clone(); 16418 } 16419 16420 if (this.maxDate && calendar[row][col].format('YYYY-MM-DD') == this.maxDate.format('YYYY-MM-DD') && calendar[row][col].isAfter(this.maxDate) && side == 'right') { 16421 calendar[row][col] = this.maxDate.clone(); 16422 } 16423 16424 } 16425 16426 //make the calendar object available to hoverDate/clickDate 16427 if (side == 'left') { 16428 this.leftCalendar.calendar = calendar; 16429 } else { 16430 this.rightCalendar.calendar = calendar; 16431 } 16432 16433 // 16434 // Display the calendar 16435 // 16436 16437 var minDate = side == 'left' ? this.minDate : this.startDate; 16438 var maxDate = this.maxDate; 16439 var selected = side == 'left' ? this.startDate : this.endDate; 16440 var arrow = this.locale.direction == 'ltr' ? {left: 'chevron-left', right: 'chevron-right'} : {left: 'chevron-right', right: 'chevron-left'}; 16441 16442 var html = '<table class="table-condensed">'; 16443 html += '<thead>'; 16444 html += '<tr>'; 16445 16446 // add empty cell for week number 16447 if (this.showWeekNumbers || this.showISOWeekNumbers) 16448 html += '<th></th>'; 16449 16450 if ((!minDate || minDate.isBefore(calendar.firstDay)) && (!this.linkedCalendars || side == 'left')) { 16451 html += '<th class="prev available"><span></span></th>'; 16452 } else { 16453 html += '<th></th>'; 16454 } 16455 16456 var dateHtml = this.locale.monthNames[calendar[1][1].month()] + calendar[1][1].format(" YYYY"); 16457 16458 if (this.showDropdowns) { 16459 var currentMonth = calendar[1][1].month(); 16460 var currentYear = calendar[1][1].year(); 16461 var maxYear = (maxDate && maxDate.year()) || (this.maxYear); 16462 var minYear = (minDate && minDate.year()) || (this.minYear); 16463 var inMinYear = currentYear == minYear; 16464 var inMaxYear = currentYear == maxYear; 16465 16466 var monthHtml = '<select class="monthselect">'; 16467 for (var m = 0; m < 12; m++) { 16468 if ((!inMinYear || (minDate && m >= minDate.month())) && (!inMaxYear || (maxDate && m <= maxDate.month()))) { 16469 monthHtml += "<option value='" + m + "'" + 16470 (m === currentMonth ? " selected='selected'" : "") + 16471 ">" + this.locale.monthNames[m] + "</option>"; 16472 } else { 16473 monthHtml += "<option value='" + m + "'" + 16474 (m === currentMonth ? " selected='selected'" : "") + 16475 " disabled='disabled'>" + this.locale.monthNames[m] + "</option>"; 16476 } 16477 } 16478 monthHtml += "</select>"; 16479 16480 var yearHtml = '<select class="yearselect">'; 16481 for (var y = minYear; y <= maxYear; y++) { 16482 yearHtml += '<option value="' + y + '"' + 16483 (y === currentYear ? ' selected="selected"' : '') + 16484 '>' + y + '</option>'; 16485 } 16486 yearHtml += '</select>'; 16487 16488 dateHtml = monthHtml + yearHtml; 16489 } 16490 16491 html += '<th colspan="5" class="month">' + dateHtml + '</th>'; 16492 if ((!maxDate || maxDate.isAfter(calendar.lastDay)) && (!this.linkedCalendars || side == 'right' || this.singleDatePicker)) { 16493 html += '<th class="next available"><span></span></th>'; 16494 } else { 16495 html += '<th></th>'; 16496 } 16497 16498 html += '</tr>'; 16499 html += '<tr>'; 16500 16501 // add week number label 16502 if (this.showWeekNumbers || this.showISOWeekNumbers) 16503 html += '<th class="week">' + this.locale.weekLabel + '</th>'; 16504 16505 $.each(this.locale.daysOfWeek, function(index, dayOfWeek) { 16506 html += '<th>' + dayOfWeek + '</th>'; 16507 }); 16508 16509 html += '</tr>'; 16510 html += '</thead>'; 16511 html += '<tbody>'; 16512 16513 //adjust maxDate to reflect the maxSpan setting in order to 16514 //grey out end dates beyond the maxSpan 16515 if (this.endDate == null && this.maxSpan) { 16516 var maxLimit = this.startDate.clone().add(this.maxSpan).endOf('day'); 16517 if (!maxDate || maxLimit.isBefore(maxDate)) { 16518 maxDate = maxLimit; 16519 } 16520 } 16521 16522 for (var row = 0; row < 6; row++) { 16523 html += '<tr>'; 16524 16525 // add week number 16526 if (this.showWeekNumbers) 16527 html += '<td class="week">' + calendar[row][0].week() + '</td>'; 16528 else if (this.showISOWeekNumbers) 16529 html += '<td class="week">' + calendar[row][0].isoWeek() + '</td>'; 16530 16531 for (var col = 0; col < 7; col++) { 16532 16533 var classes = []; 16534 16535 //highlight today's date 16536 if (calendar[row][col].isSame(new Date(), "day")) 16537 classes.push('today'); 16538 16539 //highlight weekends 16540 if (calendar[row][col].isoWeekday() > 5) 16541 classes.push('weekend'); 16542 16543 //grey out the dates in other months displayed at beginning and end of this calendar 16544 if (calendar[row][col].month() != calendar[1][1].month()) 16545 classes.push('off', 'ends'); 16546 16547 //don't allow selection of dates before the minimum date 16548 if (this.minDate && calendar[row][col].isBefore(this.minDate, 'day')) 16549 classes.push('off', 'disabled'); 16550 16551 //don't allow selection of dates after the maximum date 16552 if (maxDate && calendar[row][col].isAfter(maxDate, 'day')) 16553 classes.push('off', 'disabled'); 16554 16555 //don't allow selection of date if a custom function decides it's invalid 16556 if (this.isInvalidDate(calendar[row][col])) 16557 classes.push('off', 'disabled'); 16558 16559 //highlight the currently selected start date 16560 if (calendar[row][col].format('YYYY-MM-DD') == this.startDate.format('YYYY-MM-DD')) 16561 classes.push('active', 'start-date'); 16562 16563 //highlight the currently selected end date 16564 if (this.endDate != null && calendar[row][col].format('YYYY-MM-DD') == this.endDate.format('YYYY-MM-DD')) 16565 classes.push('active', 'end-date'); 16566 16567 //highlight dates in-between the selected dates 16568 if (this.endDate != null && calendar[row][col] > this.startDate && calendar[row][col] < this.endDate) 16569 classes.push('in-range'); 16570 16571 //apply custom classes for this date 16572 var isCustom = this.isCustomDate(calendar[row][col]); 16573 if (isCustom !== false) { 16574 if (typeof isCustom === 'string') 16575 classes.push(isCustom); 16576 else 16577 Array.prototype.push.apply(classes, isCustom); 16578 } 16579 16580 var cname = '', disabled = false; 16581 for (var i = 0; i < classes.length; i++) { 16582 cname += classes[i] + ' '; 16583 if (classes[i] == 'disabled') 16584 disabled = true; 16585 } 16586 if (!disabled) 16587 cname += 'available'; 16588 16589 html += '<td class="' + cname.replace(/^\s+|\s+$/g, '') + '" data-title="' + 'r' + row + 'c' + col + '">' + calendar[row][col].date() + '</td>'; 16590 16591 } 16592 html += '</tr>'; 16593 } 16594 16595 html += '</tbody>'; 16596 html += '</table>'; 16597 16598 this.container.find('.drp-calendar.' + side + ' .calendar-table').html(html); 16599 16600 }, 16601 16602 renderTimePicker: function(side) { 16603 16604 // Don't bother updating the time picker if it's currently disabled 16605 // because an end date hasn't been clicked yet 16606 if (side == 'right' && !this.endDate) return; 16607 16608 var html, selected, minDate, maxDate = this.maxDate; 16609 16610 if (this.maxSpan && (!this.maxDate || this.startDate.clone().add(this.maxSpan).isBefore(this.maxDate))) 16611 maxDate = this.startDate.clone().add(this.maxSpan); 16612 16613 if (side == 'left') { 16614 selected = this.startDate.clone(); 16615 minDate = this.minDate; 16616 } else if (side == 'right') { 16617 selected = this.endDate.clone(); 16618 minDate = this.startDate; 16619 16620 //Preserve the time already selected 16621 var timeSelector = this.container.find('.drp-calendar.right .calendar-time'); 16622 if (timeSelector.html() != '') { 16623 16624 selected.hour(!isNaN(selected.hour()) ? selected.hour() : timeSelector.find('.hourselect option:selected').val()); 16625 selected.minute(!isNaN(selected.minute()) ? selected.minute() : timeSelector.find('.minuteselect option:selected').val()); 16626 selected.second(!isNaN(selected.second()) ? selected.second() : timeSelector.find('.secondselect option:selected').val()); 16627 16628 if (!this.timePicker24Hour) { 16629 var ampm = timeSelector.find('.ampmselect option:selected').val(); 16630 if (ampm === 'PM' && selected.hour() < 12) 16631 selected.hour(selected.hour() + 12); 16632 if (ampm === 'AM' && selected.hour() === 12) 16633 selected.hour(0); 16634 } 16635 16636 } 16637 16638 if (selected.isBefore(this.startDate)) 16639 selected = this.startDate.clone(); 16640 16641 if (maxDate && selected.isAfter(maxDate)) 16642 selected = maxDate.clone(); 16643 16644 } 16645 16646 // 16647 // hours 16648 // 16649 16650 html = '<select class="hourselect">'; 16651 16652 var start = this.timePicker24Hour ? 0 : 1; 16653 var end = this.timePicker24Hour ? 23 : 12; 16654 16655 for (var i = start; i <= end; i++) { 16656 var i_in_24 = i; 16657 if (!this.timePicker24Hour) 16658 i_in_24 = selected.hour() >= 12 ? (i == 12 ? 12 : i + 12) : (i == 12 ? 0 : i); 16659 16660 var time = selected.clone().hour(i_in_24); 16661 var disabled = false; 16662 if (minDate && time.minute(59).isBefore(minDate)) 16663 disabled = true; 16664 if (maxDate && time.minute(0).isAfter(maxDate)) 16665 disabled = true; 16666 16667 if (i_in_24 == selected.hour() && !disabled) { 16668 html += '<option value="' + i + '" selected="selected">' + i + '</option>'; 16669 } else if (disabled) { 16670 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + i + '</option>'; 16671 } else { 16672 html += '<option value="' + i + '">' + i + '</option>'; 16673 } 16674 } 16675 16676 html += '</select> '; 16677 16678 // 16679 // minutes 16680 // 16681 16682 html += ': <select class="minuteselect">'; 16683 16684 for (var i = 0; i < 60; i += this.timePickerIncrement) { 16685 var padded = i < 10 ? '0' + i : i; 16686 var time = selected.clone().minute(i); 16687 16688 var disabled = false; 16689 if (minDate && time.second(59).isBefore(minDate)) 16690 disabled = true; 16691 if (maxDate && time.second(0).isAfter(maxDate)) 16692 disabled = true; 16693 16694 if (selected.minute() == i && !disabled) { 16695 html += '<option value="' + i + '" selected="selected">' + padded + '</option>'; 16696 } else if (disabled) { 16697 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>'; 16698 } else { 16699 html += '<option value="' + i + '">' + padded + '</option>'; 16700 } 16701 } 16702 16703 html += '</select> '; 16704 16705 // 16706 // seconds 16707 // 16708 16709 if (this.timePickerSeconds) { 16710 html += ': <select class="secondselect">'; 16711 16712 for (var i = 0; i < 60; i++) { 16713 var padded = i < 10 ? '0' + i : i; 16714 var time = selected.clone().second(i); 16715 16716 var disabled = false; 16717 if (minDate && time.isBefore(minDate)) 16718 disabled = true; 16719 if (maxDate && time.isAfter(maxDate)) 16720 disabled = true; 16721 16722 if (selected.second() == i && !disabled) { 16723 html += '<option value="' + i + '" selected="selected">' + padded + '</option>'; 16724 } else if (disabled) { 16725 html += '<option value="' + i + '" disabled="disabled" class="disabled">' + padded + '</option>'; 16726 } else { 16727 html += '<option value="' + i + '">' + padded + '</option>'; 16728 } 16729 } 16730 16731 html += '</select> '; 16732 } 16733 16734 // 16735 // AM/PM 16736 // 16737 16738 if (!this.timePicker24Hour) { 16739 html += '<select class="ampmselect">'; 16740 16741 var am_html = ''; 16742 var pm_html = ''; 16743 16744 if (minDate && selected.clone().hour(12).minute(0).second(0).isBefore(minDate)) 16745 am_html = ' disabled="disabled" class="disabled"'; 16746 16747 if (maxDate && selected.clone().hour(0).minute(0).second(0).isAfter(maxDate)) 16748 pm_html = ' disabled="disabled" class="disabled"'; 16749 16750 if (selected.hour() >= 12) { 16751 html += '<option value="AM"' + am_html + '>AM</option><option value="PM" selected="selected"' + pm_html + '>PM</option>'; 16752 } else { 16753 html += '<option value="AM" selected="selected"' + am_html + '>AM</option><option value="PM"' + pm_html + '>PM</option>'; 16754 } 16755 16756 html += '</select>'; 16757 } 16758 16759 this.container.find('.drp-calendar.' + side + ' .calendar-time').html(html); 16760 16761 }, 16762 16763 updateFormInputs: function() { 16764 16765 if (this.singleDatePicker || (this.endDate && (this.startDate.isBefore(this.endDate) || this.startDate.isSame(this.endDate)))) { 16766 this.container.find('button.applyBtn').removeAttr('disabled'); 16767 } else { 16768 this.container.find('button.applyBtn').attr('disabled', 'disabled'); 16769 } 16770 16771 }, 16772 16773 move: function() { 16774 var parentOffset = { top: 0, left: 0 }, 16775 containerTop; 16776 var parentRightEdge = $(window).width(); 16777 if (!this.parentEl.is('body')) { 16778 parentOffset = { 16779 top: this.parentEl.offset().top - this.parentEl.scrollTop(), 16780 left: this.parentEl.offset().left - this.parentEl.scrollLeft() 16781 }; 16782 parentRightEdge = this.parentEl[0].clientWidth + this.parentEl.offset().left; 16783 } 16784 16785 if (this.drops == 'up') 16786 containerTop = this.element.offset().top - this.container.outerHeight() - parentOffset.top; 16787 else 16788 containerTop = this.element.offset().top + this.element.outerHeight() - parentOffset.top; 16789 16790 // Force the container to it's actual width 16791 this.container.css({ 16792 top: 0, 16793 left: 0, 16794 right: 'auto' 16795 }); 16796 var containerWidth = this.container.outerWidth(); 16797 16798 this.container[this.drops == 'up' ? 'addClass' : 'removeClass']('drop-up'); 16799 16800 if (this.opens == 'left') { 16801 var containerRight = parentRightEdge - this.element.offset().left - this.element.outerWidth(); 16802 if (containerWidth + containerRight > $(window).width()) { 16803 this.container.css({ 16804 top: containerTop, 16805 right: 'auto', 16806 left: 9 16807 }); 16808 } else { 16809 this.container.css({ 16810 top: containerTop, 16811 right: containerRight, 16812 left: 'auto' 16813 }); 16814 } 16815 } else if (this.opens == 'center') { 16816 var containerLeft = this.element.offset().left - parentOffset.left + this.element.outerWidth() / 2 16817 - containerWidth / 2; 16818 if (containerLeft < 0) { 16819 this.container.css({ 16820 top: containerTop, 16821 right: 'auto', 16822 left: 9 16823 }); 16824 } else if (containerLeft + containerWidth > $(window).width()) { 16825 this.container.css({ 16826 top: containerTop, 16827 left: 'auto', 16828 right: 0 16829 }); 16830 } else { 16831 this.container.css({ 16832 top: containerTop, 16833 left: containerLeft, 16834 right: 'auto' 16835 }); 16836 } 16837 } else { 16838 var containerLeft = this.element.offset().left - parentOffset.left; 16839 if (containerLeft + containerWidth > $(window).width()) { 16840 this.container.css({ 16841 top: containerTop, 16842 left: 'auto', 16843 right: 0 16844 }); 16845 } else { 16846 this.container.css({ 16847 top: containerTop, 16848 left: containerLeft, 16849 right: 'auto' 16850 }); 16851 } 16852 } 16853 }, 16854 16855 show: function(e) { 16856 if (this.isShowing) return; 16857 16858 // Create a click proxy that is private to this instance of datepicker, for unbinding 16859 this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this); 16860 16861 // Bind global datepicker mousedown for hiding and 16862 $(document) 16863 .on('mousedown.daterangepicker', this._outsideClickProxy) 16864 // also support mobile devices 16865 .on('touchend.daterangepicker', this._outsideClickProxy) 16866 // also explicitly play nice with Bootstrap dropdowns, which stopPropagation when clicking them 16867 .on('click.daterangepicker', '[data-toggle=dropdown]', this._outsideClickProxy) 16868 // and also close when focus changes to outside the picker (eg. tabbing between controls) 16869 .on('focusin.daterangepicker', this._outsideClickProxy); 16870 16871 // Reposition the picker if the window is resized while it's open 16872 $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this)); 16873 16874 this.oldStartDate = this.startDate.clone(); 16875 this.oldEndDate = this.endDate.clone(); 16876 this.previousRightTime = this.endDate.clone(); 16877 16878 this.updateView(); 16879 this.container.show(); 16880 this.move(); 16881 this.element.trigger('show.daterangepicker', this); 16882 this.isShowing = true; 16883 }, 16884 16885 hide: function(e) { 16886 if (!this.isShowing) return; 16887 16888 //incomplete date selection, revert to last values 16889 if (!this.endDate) { 16890 this.startDate = this.oldStartDate.clone(); 16891 this.endDate = this.oldEndDate.clone(); 16892 } 16893 16894 //if a new date range was selected, invoke the user callback function 16895 if (!this.startDate.isSame(this.oldStartDate) || !this.endDate.isSame(this.oldEndDate)) 16896 this.callback(this.startDate.clone(), this.endDate.clone(), this.chosenLabel); 16897 16898 //if picker is attached to a text input, update it 16899 this.updateElement(); 16900 16901 $(document).off('.daterangepicker'); 16902 $(window).off('.daterangepicker'); 16903 this.container.hide(); 16904 this.element.trigger('hide.daterangepicker', this); 16905 this.isShowing = false; 16906 }, 16907 16908 toggle: function(e) { 16909 if (this.isShowing) { 16910 this.hide(); 16911 } else { 16912 this.show(); 16913 } 16914 }, 16915 16916 outsideClick: function(e) { 16917 var target = $(e.target); 16918 // if the page is clicked anywhere except within the daterangerpicker/button 16919 // itself then call this.hide() 16920 if ( 16921 // ie modal dialog fix 16922 e.type == "focusin" || 16923 target.closest(this.element).length || 16924 target.closest(this.container).length || 16925 target.closest('.calendar-table').length 16926 ) return; 16927 this.hide(); 16928 this.element.trigger('outsideClick.daterangepicker', this); 16929 }, 16930 16931 showCalendars: function() { 16932 this.container.addClass('show-calendar'); 16933 this.move(); 16934 this.element.trigger('showCalendar.daterangepicker', this); 16935 }, 16936 16937 hideCalendars: function() { 16938 this.container.removeClass('show-calendar'); 16939 this.element.trigger('hideCalendar.daterangepicker', this); 16940 }, 16941 16942 clickRange: function(e) { 16943 var label = e.target.getAttribute('data-range-key'); 16944 this.chosenLabel = label; 16945 if (label == this.locale.customRangeLabel) { 16946 this.showCalendars(); 16947 } else { 16948 var dates = this.ranges[label]; 16949 this.startDate = dates[0]; 16950 this.endDate = dates[1]; 16951 16952 if (!this.timePicker) { 16953 this.startDate.startOf('day'); 16954 this.endDate.endOf('day'); 16955 } 16956 16957 if (!this.alwaysShowCalendars) 16958 this.hideCalendars(); 16959 this.clickApply(); 16960 } 16961 }, 16962 16963 clickPrev: function(e) { 16964 var cal = $(e.target).parents('.drp-calendar'); 16965 if (cal.hasClass('left')) { 16966 this.leftCalendar.month.subtract(1, 'month'); 16967 if (this.linkedCalendars) 16968 this.rightCalendar.month.subtract(1, 'month'); 16969 } else { 16970 this.rightCalendar.month.subtract(1, 'month'); 16971 } 16972 this.updateCalendars(); 16973 }, 16974 16975 clickNext: function(e) { 16976 var cal = $(e.target).parents('.drp-calendar'); 16977 if (cal.hasClass('left')) { 16978 this.leftCalendar.month.add(1, 'month'); 16979 } else { 16980 this.rightCalendar.month.add(1, 'month'); 16981 if (this.linkedCalendars) 16982 this.leftCalendar.month.add(1, 'month'); 16983 } 16984 this.updateCalendars(); 16985 }, 16986 16987 hoverDate: function(e) { 16988 16989 //ignore dates that can't be selected 16990 if (!$(e.target).hasClass('available')) return; 16991 16992 var title = $(e.target).attr('data-title'); 16993 var row = title.substr(1, 1); 16994 var col = title.substr(3, 1); 16995 var cal = $(e.target).parents('.drp-calendar'); 16996 var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; 16997 16998 //highlight the dates between the start date and the date being hovered as a potential end date 16999 var leftCalendar = this.leftCalendar; 17000 var rightCalendar = this.rightCalendar; 17001 var startDate = this.startDate; 17002 if (!this.endDate) { 17003 this.container.find('.drp-calendar tbody td').each(function(index, el) { 17004 17005 //skip week numbers, only look at dates 17006 if ($(el).hasClass('week')) return; 17007 17008 var title = $(el).attr('data-title'); 17009 var row = title.substr(1, 1); 17010 var col = title.substr(3, 1); 17011 var cal = $(el).parents('.drp-calendar'); 17012 var dt = cal.hasClass('left') ? leftCalendar.calendar[row][col] : rightCalendar.calendar[row][col]; 17013 17014 if ((dt.isAfter(startDate) && dt.isBefore(date)) || dt.isSame(date, 'day')) { 17015 $(el).addClass('in-range'); 17016 } else { 17017 $(el).removeClass('in-range'); 17018 } 17019 17020 }); 17021 } 17022 17023 }, 17024 17025 clickDate: function(e) { 17026 17027 if (!$(e.target).hasClass('available')) return; 17028 17029 var title = $(e.target).attr('data-title'); 17030 var row = title.substr(1, 1); 17031 var col = title.substr(3, 1); 17032 var cal = $(e.target).parents('.drp-calendar'); 17033 var date = cal.hasClass('left') ? this.leftCalendar.calendar[row][col] : this.rightCalendar.calendar[row][col]; 17034 17035 // 17036 // this function needs to do a few things: 17037 // * alternate between selecting a start and end date for the range, 17038 // * if the time picker is enabled, apply the hour/minute/second from the select boxes to the clicked date 17039 // * if autoapply is enabled, and an end date was chosen, apply the selection 17040 // * if single date picker mode, and time picker isn't enabled, apply the selection immediately 17041 // * if one of the inputs above the calendars was focused, cancel that manual input 17042 // 17043 17044 if (this.endDate || date.isBefore(this.startDate, 'day')) { //picking start 17045 if (this.timePicker) { 17046 var hour = parseInt(this.container.find('.left .hourselect').val(), 10); 17047 if (!this.timePicker24Hour) { 17048 var ampm = this.container.find('.left .ampmselect').val(); 17049 if (ampm === 'PM' && hour < 12) 17050 hour += 12; 17051 if (ampm === 'AM' && hour === 12) 17052 hour = 0; 17053 } 17054 var minute = parseInt(this.container.find('.left .minuteselect').val(), 10); 17055 if (isNaN(minute)) { 17056 minute = parseInt(this.container.find('.left .minuteselect option:last').val(), 10); 17057 } 17058 var second = this.timePickerSeconds ? parseInt(this.container.find('.left .secondselect').val(), 10) : 0; 17059 date = date.clone().hour(hour).minute(minute).second(second); 17060 } 17061 this.endDate = null; 17062 this.setStartDate(date.clone()); 17063 } else if (!this.endDate && date.isBefore(this.startDate)) { 17064 //special case: clicking the same date for start/end, 17065 //but the time of the end date is before the start date 17066 this.setEndDate(this.startDate.clone()); 17067 } else { // picking end 17068 if (this.timePicker) { 17069 var hour = parseInt(this.container.find('.right .hourselect').val(), 10); 17070 if (!this.timePicker24Hour) { 17071 var ampm = this.container.find('.right .ampmselect').val(); 17072 if (ampm === 'PM' && hour < 12) 17073 hour += 12; 17074 if (ampm === 'AM' && hour === 12) 17075 hour = 0; 17076 } 17077 var minute = parseInt(this.container.find('.right .minuteselect').val(), 10); 17078 if (isNaN(minute)) { 17079 minute = parseInt(this.container.find('.right .minuteselect option:last').val(), 10); 17080 } 17081 var second = this.timePickerSeconds ? parseInt(this.container.find('.right .secondselect').val(), 10) : 0; 17082 date = date.clone().hour(hour).minute(minute).second(second); 17083 } 17084 this.setEndDate(date.clone()); 17085 if (this.autoApply) { 17086 this.calculateChosenLabel(); 17087 this.clickApply(); 17088 } 17089 } 17090 17091 if (this.singleDatePicker) { 17092 this.setEndDate(this.startDate); 17093 if (!this.timePicker) 17094 this.clickApply(); 17095 } 17096 17097 this.updateView(); 17098 17099 //This is to cancel the blur event handler if the mouse was in one of the inputs 17100 e.stopPropagation(); 17101 17102 }, 17103 17104 calculateChosenLabel: function () { 17105 var customRange = true; 17106 var i = 0; 17107 for (var range in this.ranges) { 17108 if (this.timePicker) { 17109 var format = this.timePickerSeconds ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD HH:mm"; 17110 //ignore times when comparing dates if time picker seconds is not enabled 17111 if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) { 17112 customRange = false; 17113 this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key'); 17114 break; 17115 } 17116 } else { 17117 //ignore times when comparing dates if time picker is not enabled 17118 if (this.startDate.format('YYYY-MM-DD') == this.ranges[range][0].format('YYYY-MM-DD') && this.endDate.format('YYYY-MM-DD') == this.ranges[range][1].format('YYYY-MM-DD')) { 17119 customRange = false; 17120 this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').attr('data-range-key'); 17121 break; 17122 } 17123 } 17124 i++; 17125 } 17126 if (customRange) { 17127 if (this.showCustomRangeLabel) { 17128 this.chosenLabel = this.container.find('.ranges li:last').addClass('active').attr('data-range-key'); 17129 } else { 17130 this.chosenLabel = null; 17131 } 17132 this.showCalendars(); 17133 } 17134 }, 17135 17136 clickApply: function(e) { 17137 this.hide(); 17138 this.element.trigger('apply.daterangepicker', this); 17139 }, 17140 17141 clickCancel: function(e) { 17142 this.startDate = this.oldStartDate; 17143 this.endDate = this.oldEndDate; 17144 this.hide(); 17145 this.element.trigger('cancel.daterangepicker', this); 17146 }, 17147 17148 monthOrYearChanged: function(e) { 17149 var isLeft = $(e.target).closest('.drp-calendar').hasClass('left'), 17150 leftOrRight = isLeft ? 'left' : 'right', 17151 cal = this.container.find('.drp-calendar.'+leftOrRight); 17152 17153 // Month must be Number for new moment versions 17154 var month = parseInt(cal.find('.monthselect').val(), 10); 17155 var year = cal.find('.yearselect').val(); 17156 17157 if (!isLeft) { 17158 if (year < this.startDate.year() || (year == this.startDate.year() && month < this.startDate.month())) { 17159 month = this.startDate.month(); 17160 year = this.startDate.year(); 17161 } 17162 } 17163 17164 if (this.minDate) { 17165 if (year < this.minDate.year() || (year == this.minDate.year() && month < this.minDate.month())) { 17166 month = this.minDate.month(); 17167 year = this.minDate.year(); 17168 } 17169 } 17170 17171 if (this.maxDate) { 17172 if (year > this.maxDate.year() || (year == this.maxDate.year() && month > this.maxDate.month())) { 17173 month = this.maxDate.month(); 17174 year = this.maxDate.year(); 17175 } 17176 } 17177 17178 if (isLeft) { 17179 this.leftCalendar.month.month(month).year(year); 17180 if (this.linkedCalendars) 17181 this.rightCalendar.month = this.leftCalendar.month.clone().add(1, 'month'); 17182 } else { 17183 this.rightCalendar.month.month(month).year(year); 17184 if (this.linkedCalendars) 17185 this.leftCalendar.month = this.rightCalendar.month.clone().subtract(1, 'month'); 17186 } 17187 this.updateCalendars(); 17188 }, 17189 17190 timeChanged: function(e) { 17191 17192 var cal = $(e.target).closest('.drp-calendar'), 17193 isLeft = cal.hasClass('left'); 17194 17195 var hour = parseInt(cal.find('.hourselect').val(), 10); 17196 var minute = parseInt(cal.find('.minuteselect').val(), 10); 17197 if (isNaN(minute)) { 17198 minute = parseInt(cal.find('.minuteselect option:last').val(), 10); 17199 } 17200 var second = this.timePickerSeconds ? parseInt(cal.find('.secondselect').val(), 10) : 0; 17201 17202 if (!this.timePicker24Hour) { 17203 var ampm = cal.find('.ampmselect').val(); 17204 if (ampm === 'PM' && hour < 12) 17205 hour += 12; 17206 if (ampm === 'AM' && hour === 12) 17207 hour = 0; 17208 } 17209 17210 if (isLeft) { 17211 var start = this.startDate.clone(); 17212 start.hour(hour); 17213 start.minute(minute); 17214 start.second(second); 17215 this.setStartDate(start); 17216 if (this.singleDatePicker) { 17217 this.endDate = this.startDate.clone(); 17218 } else if (this.endDate && this.endDate.format('YYYY-MM-DD') == start.format('YYYY-MM-DD') && this.endDate.isBefore(start)) { 17219 this.setEndDate(start.clone()); 17220 } 17221 } else if (this.endDate) { 17222 var end = this.endDate.clone(); 17223 end.hour(hour); 17224 end.minute(minute); 17225 end.second(second); 17226 this.setEndDate(end); 17227 } 17228 17229 //update the calendars so all clickable dates reflect the new time component 17230 this.updateCalendars(); 17231 17232 //update the form inputs above the calendars with the new time 17233 this.updateFormInputs(); 17234 17235 //re-render the time pickers because changing one selection can affect what's enabled in another 17236 this.renderTimePicker('left'); 17237 this.renderTimePicker('right'); 17238 17239 }, 17240 17241 elementChanged: function() { 17242 if (!this.element.is('input')) return; 17243 if (!this.element.val().length) return; 17244 17245 var dateString = this.element.val().split(this.locale.separator), 17246 start = null, 17247 end = null; 17248 17249 if (dateString.length === 2) { 17250 start = moment(dateString[0], this.locale.format); 17251 end = moment(dateString[1], this.locale.format); 17252 } 17253 17254 if (this.singleDatePicker || start === null || end === null) { 17255 start = moment(this.element.val(), this.locale.format); 17256 end = start; 17257 } 17258 17259 if (!start.isValid() || !end.isValid()) return; 17260 17261 this.setStartDate(start); 17262 this.setEndDate(end); 17263 this.updateView(); 17264 }, 17265 17266 keydown: function(e) { 17267 //hide on tab or enter 17268 if ((e.keyCode === 9) || (e.keyCode === 13)) { 17269 this.hide(); 17270 } 17271 17272 //hide on esc and prevent propagation 17273 if (e.keyCode === 27) { 17274 e.preventDefault(); 17275 e.stopPropagation(); 17276 17277 this.hide(); 17278 } 17279 }, 17280 17281 updateElement: function() { 17282 if (this.element.is('input') && this.autoUpdateInput) { 17283 var newValue = this.startDate.format(this.locale.format); 17284 if (!this.singleDatePicker) { 17285 newValue += this.locale.separator + this.endDate.format(this.locale.format); 17286 } 17287 if (newValue !== this.element.val()) { 17288 this.element.val(newValue).trigger('change'); 17289 } 17290 } 17291 }, 17292 17293 remove: function() { 17294 this.container.remove(); 17295 this.element.off('.daterangepicker'); 17296 this.element.removeData(); 17297 } 17298 17299 }; 17300 17301 $.fn.daterangepicker = function(options, callback) { 17302 var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options); 17303 this.each(function() { 17304 var el = $(this); 17305 if (el.data('daterangepicker')) 17306 el.data('daterangepicker').remove(); 17307 el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback)); 17308 }); 17309 return this; 17310 }; 17311 17312 return DateRangePicker; 17313 17314})); 17315 17316/* 17317 * Bootstrap TouchSpin - v4.2.5 17318 * A mobile and touch friendly input spinner component for Bootstrap 3 & 4. 17319 * http://www.virtuosoft.eu/code/bootstrap-touchspin/ 17320 * 17321 * Made by István Ujj-Mészáros 17322 * Under Apache License v2.0 License 17323 */ 17324(function(factory) { 17325 if (typeof define === 'function' && define.amd) { 17326 define(['jquery'], factory); 17327 } else if (typeof module === 'object' && module.exports) { 17328 module.exports = function(root, jQuery) { 17329 if (jQuery === undefined) { 17330 if (typeof window !== 'undefined') { 17331 jQuery = require('jquery'); 17332 } 17333 else { 17334 jQuery = require('jquery')(root); 17335 } 17336 } 17337 factory(jQuery); 17338 return jQuery; 17339 }; 17340 } else { 17341 factory(jQuery); 17342 } 17343}(function($) { 17344 'use strict'; 17345 17346 var _currentSpinnerId = 0; 17347 17348 $.fn.TouchSpin = function(options) { 17349 17350 var defaults = { 17351 min: 0, // If null, there is no minimum enforced 17352 max: 100, // If null, there is no maximum enforced 17353 initval: '', 17354 replacementval: '', 17355 step: 1, 17356 decimals: 0, 17357 stepinterval: 100, 17358 forcestepdivisibility: 'round', // none | floor | round | ceil 17359 stepintervaldelay: 500,
17360 verticalbuttons: false, 17361 verticalup: '+', 17362 verticaldown: '-', 17363 verticalupclass: '', 17364 verticaldownclass: '', 17365 prefix: '', 17366 postfix: '', 17367 prefix_extraclass: '', 17368 postfix_extraclass: '', 17369 booster: true, 17370 boostat: 10, 17371 maxboostedstep: false, 17372 mousewheel: true, 17373 buttondown_class: 'btn btn-primary', 17374 buttonup_class: 'btn btn-primary', 17375 buttondown_txt: '-', 17376 buttonup_txt: '+', 17377 callback_before_calculation: function(value) { 17378 return value; 17379 }, 17380 callback_after_calculation: function(value) { 17381 return value; 17382 } 17383 }; 17384 17385 var attributeMap = { 17386 min: 'min', 17387 max: 'max', 17388 initval: 'init-val', 17389 replacementval: 'replacement-val', 17390 step: 'step', 17391 decimals: 'decimals', 17392 stepinterval: 'step-interval', 17393 verticalbuttons: 'vertical-buttons', 17394 verticalupclass: 'vertical-up-class', 17395 verticaldownclass: 'vertical-down-class', 17396 forcestepdivisibility: 'force-step-divisibility', 17397 stepintervaldelay: 'step-interval-delay', 17398 prefix: 'prefix', 17399 postfix: 'postfix', 17400 prefix_extraclass: 'prefix-extra-class', 17401 postfix_extraclass: 'postfix-extra-class', 17402 booster: 'booster', 17403 boostat: 'boostat', 17404 maxboostedstep: 'max-boosted-step', 17405 mousewheel: 'mouse-wheel', 17406 buttondown_class: 'button-down-class', 17407 buttonup_class: 'button-up-class', 17408 buttondown_txt: 'button-down-txt', 17409 buttonup_txt: 'button-up-txt' 17410 }; 17411 17412 return this.each(function() { 17413 17414 var settings, 17415 originalinput = $(this), 17416 originalinput_data = originalinput.data(), 17417 _detached_prefix, 17418 _detached_postfix, 17419 container, 17420 elements, 17421 value, 17422 downSpinTimer, 17423 upSpinTimer, 17424 downDelayTimeout, 17425 upDelayTimeout, 17426 spincount = 0, 17427 spinning = false; 17428 17429 init(); 17430 17431 function init() { 17432 if (originalinput.data('alreadyinitialized')) { 17433 return; 17434 } 17435 17436 originalinput.data('alreadyinitialized', true); 17437 _currentSpinnerId += 1; 17438 originalinput.data('spinnerid', _currentSpinnerId); 17439 17440 if (!originalinput.is('input')) { 17441 console.log('Must be an input.'); 17442 return; 17443 } 17444 17445 _initSettings(); 17446 _setInitval(); 17447 _checkValue(); 17448 _buildHtml(); 17449 _initElements(); 17450 _hideEmptyPrefixPostfix(); 17451 _bindEvents(); 17452 _bindEventsInterface(); 17453 } 17454 17455 function _setInitval() { 17456 if (settings.initval !== '' && originalinput.val() === '') { 17457 originalinput.val(settings.initval); 17458 } 17459 } 17460 17461 function changeSettings(newsettings) { 17462 _updateSettings(newsettings); 17463 _checkValue(); 17464 17465 var value = elements.input.val(); 17466 17467 if (value !== '') { 17468 value = Number(settings.callback_before_calculation(elements.input.val())); 17469 elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals))); 17470 } 17471 } 17472 17473 function _initSettings() { 17474 settings = $.extend({}, defaults, originalinput_data, _parseAttributes(), options); 17475 } 17476 17477 function _parseAttributes() { 17478 var data = {}; 17479 $.each(attributeMap, function(key, value) { 17480 var attrName = 'bts-' + value + ''; 17481 if (originalinput.is('[data-' + attrName + ']')) { 17482 data[key] = originalinput.data(attrName); 17483 } 17484 }); 17485 return data; 17486 } 17487 17488 function _destroy() { 17489 var $parent = originalinput.parent(); 17490 17491 stopSpin(); 17492 17493 originalinput.off('.touchspin'); 17494 17495 if ($parent.hasClass('bootstrap-touchspin-injected')) { 17496 originalinput.siblings().remove(); 17497 originalinput.unwrap(); 17498 } 17499 else { 17500 $('.bootstrap-touchspin-injected', $parent).remove(); 17501 $parent.removeClass('bootstrap-touchspin'); 17502 } 17503 17504 originalinput.data('alreadyinitialized', false); 17505 } 17506 17507 function _updateSettings(newsettings) { 17508 settings = $.extend({}, settings, newsettings); 17509 17510 // Update postfix and prefix texts if those settings were changed. 17511 if (newsettings.postfix) { 17512 var $postfix = originalinput.parent().find('.bootstrap-touchspin-postfix'); 17513 17514 if ($postfix.length === 0) { 17515 _detached_postfix.insertAfter(originalinput); 17516 } 17517 17518 originalinput.parent().find('.bootstrap-touchspin-postfix .input-group-text').text(newsettings.postfix); 17519 } 17520 17521 if (newsettings.prefix) { 17522 var $prefix = originalinput.parent().find('.bootstrap-touchspin-prefix'); 17523 17524 if ($prefix.length === 0) { 17525 _detached_prefix.insertBefore(originalinput); 17526 } 17527 17528 originalinput.parent().find('.bootstrap-touchspin-prefix .input-group-text').text(newsettings.prefix); 17529 } 17530 17531 _hideEmptyPrefixPostfix(); 17532 } 17533 17534 function _buildHtml() { 17535 var initval = originalinput.val(), 17536 parentelement = originalinput.parent(); 17537 17538 if (initval !== '') { 17539 initval = settings.callback_after_calculation(Number(initval).toFixed(settings.decimals)); 17540 } 17541 17542 originalinput.data('initvalue', initval).val(initval); 17543 originalinput.addClass('form-control'); 17544 17545 if (parentelement.hasClass('input-group')) { 17546 _advanceInputGroup(parentelement); 17547 } 17548 else { 17549 _buildInputGroup(); 17550 } 17551 } 17552 17553 function _advanceInputGroup(parentelement) { 17554 parentelement.addClass('bootstrap-touchspin'); 17555 17556 var prev = originalinput.prev(), 17557 next = originalinput.next(); 17558 17559 var downhtml, 17560 uphtml, 17561 prefixhtml = '<span class="input-group-addon input-group-prepend bootstrap-touchspin-prefix input-group-prepend bootstrap-touchspin-injected"><span class="input-group-text">' + settings.prefix + '</span></span>', 17562 postfixhtml = '<span class="input-group-addon input-group-append bootstrap-touchspin-postfix input-group-append bootstrap-touchspin-injected"><span class="input-group-text">' + settings.postfix + '</span></span>'; 17563 17564 if (prev.hasClass('input-group-btn') || prev.hasClass('input-group-prepend')) { 17565 downhtml = '<button class="' + settings.buttondown_class + ' bootstrap-touchspin-down bootstrap-touchspin-injected" type="button">' + settings.buttondown_txt + '</button>'; 17566 prev.append(downhtml); 17567 } 17568 else { 17569 downhtml = '<span class="input-group-btn input-group-prepend bootstrap-touchspin-injected"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span>'; 17570 $(downhtml).insertBefore(originalinput); 17571 } 17572 17573 if (next.hasClass('input-group-btn') || next.hasClass('input-group-append')) { 17574 uphtml = '<button class="' + settings.buttonup_class + ' bootstrap-touchspin-up bootstrap-touchspin-injected" type="button">' + settings.buttonup_txt + '</button>'; 17575 next.prepend(uphtml); 17576 } 17577 else { 17578 uphtml = '<span class="input-group-btn input-group-append bootstrap-touchspin-injected"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span>'; 17579 $(uphtml).insertAfter(originalinput); 17580 } 17581 17582 $(prefixhtml).insertBefore(originalinput); 17583 $(postfixhtml).insertAfter(originalinput); 17584 17585 container = parentelement; 17586 } 17587 17588 function _buildInputGroup() { 17589 var html; 17590 17591 var inputGroupSize = ''; 17592 if (originalinput.hasClass('input-sm')) { 17593 inputGroupSize = 'input-group-sm'; 17594 } 17595 17596 if (originalinput.hasClass('input-lg')) { 17597 inputGroupSize = 'input-group-lg'; 17598 } 17599 17600 if (settings.verticalbuttons) { 17601 html = '<div class="input-group ' + inputGroupSize + ' bootstrap-touchspin bootstrap-touchspin-injected"><span class="input-group-addon input-group-prepend bootstrap-touchspin-prefix"><span class="input-group-text">' + settings.prefix + '</span></span><span class="input-group-addon bootstrap-touchspin-postfix input-group-append"><span class="input-group-text">' + settings.postfix + '</span></span><span class="input-group-btn-vertical"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-up ' + settings.verticalupclass + '" type="button">' + settings.verticalup + '</button><button class="' + settings.buttonup_class + ' bootstrap-touchspin-down ' + settings.verticaldownclass + '" type="button">' + settings.verticaldown + '</button></span></div>'; 17602 } 17603 else { 17604 html = '<div class="input-group bootstrap-touchspin bootstrap-touchspin-injected"><span class="input-group-btn input-group-prepend"><button class="' + settings.buttondown_class + ' bootstrap-touchspin-down" type="button">' + settings.buttondown_txt + '</button></span><span class="input-group-addon bootstrap-touchspin-prefix input-group-prepend"><span class="input-group-text">' + settings.prefix + '</span></span><span class="input-group-addon bootstrap-touchspin-postfix input-group-append"><span class="input-group-text">' + settings.postfix + '</span></span><span class="input-group-btn input-group-append"><button class="' + settings.buttonup_class + ' bootstrap-touchspin-up" type="button">' + settings.buttonup_txt + '</button></span></div>'; 17605 } 17606 17607 container = $(html).insertBefore(originalinput); 17608 17609 $('.bootstrap-touchspin-prefix', container).after(originalinput); 17610 17611 if (originalinput.hasClass('input-sm')) { 17612 container.addClass('input-group-sm'); 17613 } 17614 else if (originalinput.hasClass('input-lg')) { 17615 container.addClass('input-group-lg'); 17616 } 17617 } 17618 17619 function _initElements() { 17620 elements = { 17621 down: $('.bootstrap-touchspin-down', container), 17622 up: $('.bootstrap-touchspin-up', container), 17623 input: $('input', container), 17624 prefix: $('.bootstrap-touchspin-prefix', container).addClass(settings.prefix_extraclass), 17625 postfix: $('.bootstrap-touchspin-postfix', container).addClass(settings.postfix_extraclass) 17626 }; 17627 } 17628 17629 function _hideEmptyPrefixPostfix() { 17630 if (settings.prefix === '') { 17631 _detached_prefix = elements.prefix.detach(); 17632 } 17633 17634 if (settings.postfix === '') { 17635 _detached_postfix = elements.postfix.detach(); 17636 } 17637 } 17638 17639 function _bindEvents() { 17640 originalinput.on('keydown.touchspin', function(ev) { 17641 var code = ev.keyCode || ev.which; 17642 17643 if (code === 38) { 17644 if (spinning !== 'up') { 17645 upOnce(); 17646 startUpSpin(); 17647 } 17648 ev.preventDefault(); 17649 } 17650 else if (code === 40) { 17651 if (spinning !== 'down') { 17652 downOnce(); 17653 startDownSpin(); 17654 } 17655 ev.preventDefault(); 17656 } 17657 }); 17658 17659 originalinput.on('keyup.touchspin', function(ev) { 17660 var code = ev.keyCode || ev.which; 17661 17662 if (code === 38) { 17663 stopSpin(); 17664 } 17665 else if (code === 40) { 17666 stopSpin(); 17667 } 17668 }); 17669 17670 originalinput.on('blur.touchspin', function() { 17671 _checkValue(); 17672 originalinput.val(settings.callback_after_calculation(originalinput.val())); 17673 }); 17674 17675 elements.down.on('keydown', function(ev) { 17676 var code = ev.keyCode || ev.which; 17677 17678 if (code === 32 || code === 13) { 17679 if (spinning !== 'down') { 17680 downOnce(); 17681 startDownSpin(); 17682 } 17683 ev.preventDefault(); 17684 } 17685 }); 17686 17687 elements.down.on('keyup.touchspin', function(ev) { 17688 var code = ev.keyCode || ev.which; 17689 17690 if (code === 32 || code === 13) { 17691 stopSpin(); 17692 } 17693 }); 17694 17695 elements.up.on('keydown.touchspin', function(ev) { 17696 var code = ev.keyCode || ev.which; 17697 17698 if (code === 32 || code === 13) { 17699 if (spinning !== 'up') { 17700 upOnce(); 17701 startUpSpin(); 17702 } 17703 ev.preventDefault(); 17704 } 17705 }); 17706 17707 elements.up.on('keyup.touchspin', function(ev) { 17708 var code = ev.keyCode || ev.which; 17709 17710 if (code === 32 || code === 13) { 17711 stopSpin(); 17712 } 17713 }); 17714 17715 elements.down.on('mousedown.touchspin', function(ev) { 17716 elements.down.off('touchstart.touchspin'); // android 4 workaround 17717 17718 if (originalinput.is(':disabled')) { 17719 return; 17720 } 17721 17722 downOnce(); 17723 startDownSpin(); 17724 17725 ev.preventDefault(); 17726 ev.stopPropagation(); 17727 }); 17728 17729 elements.down.on('touchstart.touchspin', function(ev) { 17730 elements.down.off('mousedown.touchspin'); // android 4 workaround 17731 17732 if (originalinput.is(':disabled')) { 17733 return; 17734 } 17735 17736 downOnce(); 17737 startDownSpin(); 17738 17739 ev.preventDefault(); 17740 ev.stopPropagation(); 17741 }); 17742 17743 elements.up.on('mousedown.touchspin', function(ev) { 17744 elements.up.off('touchstart.touchspin'); // android 4 workaround 17745 17746 if (originalinput.is(':disabled')) { 17747 return; 17748 } 17749 17750 upOnce(); 17751 startUpSpin(); 17752 17753 ev.preventDefault(); 17754 ev.stopPropagation(); 17755 }); 17756 17757 elements.up.on('touchstart.touchspin', function(ev) { 17758 elements.up.off('mousedown.touchspin'); // android 4 workaround 17759 17760 if (originalinput.is(':disabled')) { 17761 return; 17762 } 17763 17764 upOnce(); 17765 startUpSpin(); 17766 17767 ev.preventDefault(); 17768 ev.stopPropagation(); 17769 }); 17770 17771 elements.up.on('mouseup.touchspin mouseout.touchspin touchleave.touchspin touchend.touchspin touchcancel.touchspin', function(ev) { 17772 if (!spinning) { 17773 return; 17774 } 17775 17776 ev.stopPropagation(); 17777 stopSpin(); 17778 }); 17779 17780 elements.down.on('mouseup.touchspin mouseout.touchspin touchleave.touchspin touchend.touchspin touchcancel.touchspin', function(ev) { 17781 if (!spinning) { 17782 return; 17783 } 17784 17785 ev.stopPropagation(); 17786 stopSpin(); 17787 }); 17788 17789 elements.down.on('mousemove.touchspin touchmove.touchspin', function(ev) { 17790 if (!spinning) { 17791 return; 17792 } 17793 17794 ev.stopPropagation(); 17795 ev.preventDefault(); 17796 }); 17797 17798 elements.up.on('mousemove.touchspin touchmove.touchspin', function(ev) { 17799 if (!spinning) { 17800 return; 17801 } 17802 17803 ev.stopPropagation(); 17804 ev.preventDefault(); 17805 }); 17806 17807 originalinput.on('mousewheel.touchspin DOMMouseScroll.touchspin', function(ev) { 17808 if (!settings.mousewheel || !originalinput.is(':focus')) { 17809 return; 17810 } 17811 17812 var delta = ev.originalEvent.wheelDelta || -ev.originalEvent.deltaY || -ev.originalEvent.detail; 17813 17814 ev.stopPropagation(); 17815 ev.preventDefault(); 17816 17817 if (delta < 0) { 17818 downOnce(); 17819 } 17820 else { 17821 upOnce(); 17822 } 17823 }); 17824 } 17825 17826 function _bindEventsInterface() { 17827 originalinput.on('touchspin.destroy', function() { 17828 _destroy(); 17829 }); 17830 17831 originalinput.on('touchspin.uponce', function() { 17832 stopSpin(); 17833 upOnce(); 17834 }); 17835 17836 originalinput.on('touchspin.downonce', function() { 17837 stopSpin(); 17838 downOnce(); 17839 }); 17840 17841 originalinput.on('touchspin.startupspin', function() { 17842 startUpSpin(); 17843 }); 17844 17845 originalinput.on('touchspin.startdownspin', function() { 17846 startDownSpin(); 17847 }); 17848 17849 originalinput.on('touchspin.stopspin', function() { 17850 stopSpin(); 17851 }); 17852 17853 originalinput.on('touchspin.updatesettings', function(e, newsettings) { 17854 changeSettings(newsettings); 17855 }); 17856 } 17857 17858 function _forcestepdivisibility(value) { 17859 switch (settings.forcestepdivisibility) { 17860 case 'round': 17861 return (Math.round(value / settings.step) * settings.step).toFixed(setting
17861s.decimals); 17862 case 'floor': 17863 return (Math.floor(value / settings.step) * settings.step).toFixed(settings.decimals); 17864 case 'ceil': 17865 return (Math.ceil(value / settings.step) * settings.step).toFixed(settings.decimals); 17866 default: 17867 return value; 17868 } 17869 } 17870 17871 function _checkValue() { 17872 var val, parsedval, returnval; 17873 17874 val = settings.callback_before_calculation(originalinput.val()); 17875 17876 if (val === '') { 17877 if (settings.replacementval !== '') { 17878 originalinput.val(settings.replacementval); 17879 originalinput.trigger('change'); 17880 } 17881 return; 17882 } 17883 17884 if (settings.decimals > 0 && val === '.') { 17885 return; 17886 } 17887 17888 parsedval = parseFloat(val); 17889 17890 if (isNaN(parsedval)) { 17891 if (settings.replacementval !== '') { 17892 parsedval = settings.replacementval; 17893 } 17894 else { 17895 parsedval = 0; 17896 } 17897 } 17898 17899 returnval = parsedval; 17900 17901 if (parsedval.toString() !== val) { 17902 returnval = parsedval; 17903 } 17904 17905 if ((settings.min !== null) && (parsedval < settings.min)) { 17906 returnval = settings.min; 17907 } 17908 17909 if ((settings.max !== null) && (parsedval > settings.max)) { 17910 returnval = settings.max; 17911 } 17912 17913 returnval = _forcestepdivisibility(returnval); 17914 17915 if (Number(val).toString() !== returnval.toString()) { 17916 originalinput.val(returnval); 17917 originalinput.trigger('change'); 17918 } 17919 } 17920 17921 function _getBoostedStep() { 17922 if (!settings.booster) { 17923 return settings.step; 17924 } 17925 else { 17926 var boosted = Math.pow(2, Math.floor(spincount / settings.boostat)) * settings.step; 17927 17928 if (settings.maxboostedstep) { 17929 if (boosted > settings.maxboostedstep) { 17930 boosted = settings.maxboostedstep; 17931 value = Math.round((value / boosted)) * boosted; 17932 } 17933 } 17934 17935 return Math.max(settings.step, boosted); 17936 } 17937 } 17938 17939 function upOnce() { 17940 _checkValue(); 17941 17942 value = parseFloat(settings.callback_before_calculation(elements.input.val())); 17943 if (isNaN(value)) { 17944 value = 0; 17945 } 17946 17947 var initvalue = value, 17948 boostedstep = _getBoostedStep(); 17949 17950 value = value + boostedstep; 17951 17952 if ((settings.max !== null) && (value > settings.max)) { 17953 value = settings.max; 17954 originalinput.trigger('touchspin.on.max'); 17955 stopSpin(); 17956 } 17957 17958 elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals))); 17959 17960 if (initvalue !== value) { 17961 originalinput.trigger('change'); 17962 } 17963 } 17964 17965 function downOnce() { 17966 _checkValue(); 17967 17968 value = parseFloat(settings.callback_before_calculation(elements.input.val())); 17969 if (isNaN(value)) { 17970 value = 0; 17971 } 17972 17973 var initvalue = value, 17974 boostedstep = _getBoostedStep(); 17975 17976 value = value - boostedstep; 17977 17978 if ((settings.min !== null) && (value < settings.min)) { 17979 value = settings.min; 17980 originalinput.trigger('touchspin.on.min'); 17981 stopSpin(); 17982 } 17983 17984 elements.input.val(settings.callback_after_calculation(Number(value).toFixed(settings.decimals))); 17985 17986 if (initvalue !== value) { 17987 originalinput.trigger('change'); 17988 } 17989 } 17990 17991 function startDownSpin() { 17992 stopSpin(); 17993 17994 spincount = 0; 17995 spinning = 'down'; 17996 17997 originalinput.trigger('touchspin.on.startspin'); 17998 originalinput.trigger('touchspin.on.startdownspin'); 17999 18000 downDelayTimeout = setTimeout(function() { 18001 downSpinTimer = setInterval(function() { 18002 spincount++; 18003 downOnce(); 18004 }, settings.stepinterval); 18005 }, settings.stepintervaldelay); 18006 } 18007 18008 function startUpSpin() { 18009 stopSpin(); 18010 18011 spincount = 0; 18012 spinning = 'up'; 18013 18014 originalinput.trigger('touchspin.on.startspin'); 18015 originalinput.trigger('touchspin.on.startupspin'); 18016 18017 upDelayTimeout = setTimeout(function() { 18018 upSpinTimer = setInterval(function() { 18019 spincount++; 18020 upOnce(); 18021 }, settings.stepinterval); 18022 }, settings.stepintervaldelay); 18023 } 18024 18025 function stopSpin() { 18026 clearTimeout(downDelayTimeout); 18027 clearTimeout(upDelayTimeout); 18028 clearInterval(downSpinTimer); 18029 clearInterval(upSpinTimer); 18030 18031 switch (spinning) { 18032 case 'up': 18033 originalinput.trigger('touchspin.on.stopupspin'); 18034 originalinput.trigger('touchspin.on.stopspin'); 18035 break; 18036 case 'down': 18037 originalinput.trigger('touchspin.on.stopdownspin'); 18038 originalinput.trigger('touchspin.on.stopspin'); 18039 break; 18040 } 18041 18042 spincount = 0; 18043 spinning = false;
18044 } 18045 18046 }); 18047 18048 }; 18049 18050})); 18051 18052(function ($) { 18053 'use strict'; 18054 /** 18055 * We need an event when the elements are destroyed 18056 * because if an input is removed, we have to remove the 18057 * maxlength object associated (if any). 18058 * From: 18059 * http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom 18060 */ 18061 if (!$.event.special.destroyed) { 18062 $.event.special.destroyed = { 18063 remove: function (o) { 18064 if (o.handler) { 18065 o.handler(); 18066 } 18067 } 18068 }; 18069 } 18070 18071 18072 $.fn.extend({ 18073 maxlength: function (options, callback) { 18074 var documentBody = $('body'), 18075 defaults = { 18076 showOnReady: false, // true to always show when indicator is ready 18077 alwaysShow: false, // if true the indicator it's always shown. 18078 threshold: 10, // Represents how many chars left are needed to show up the counter 18079 warningClass: 'label label-success', 18080 limitReachedClass: 'label label-important label-danger', 18081 separator: ' / ', 18082 preText: '', 18083 postText: '', 18084 showMaxLength: true, 18085 placement: 'bottom', 18086 message: null, // an alternative way to provide the message text 18087 showCharsTyped: true, // show the number of characters typed and not the number of characters remaining 18088 validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than 18089 // the indicated chars, will be prevented. 18090 utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters. 18091 appendToParent: false, // append the indicator to the input field's parent instead of body 18092 twoCharLinebreak: true, // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage. 18093 allowOverMax: false // false = use maxlength attribute and browswer functionality. 18094 // true = removes maxlength attribute and replaces with 'data-bs-mxl'. 18095 // Form submit validation is handled on your own. when maxlength has been exceeded 'overmax' class added to element 18096 }; 18097 18098 if ($.isFunction(options) && !callback) { 18099 callback = options; 18100 options = {}; 18101 } 18102 options = $.extend(defaults, options); 18103 18104 /** 18105 * Return the length of the specified input. 18106 * 18107 * @param input 18108 * @return {number} 18109 */ 18110 function inputLength(input) { 18111 var text = input.val(); 18112 18113 if (options.twoCharLinebreak) { 18114 // Count all line breaks as 2 characters 18115 text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n'); 18116 } else { 18117 // Remove all double-character (\r\n) linebreaks, so they're counted only once. 18118 text = text.replace(new RegExp('\r?\n', 'g'), '\n'); 18119 } 18120 18121 var currentLength = 0; 18122 18123 if (options.utf8) { 18124 currentLength = utf8Length(text); 18125 } else { 18126 currentLength = text.length; 18127 } 18128 return currentLength; 18129 } 18130 18131 /** 18132 * Truncate the text of the specified input. 18133 * 18134 * @param input 18135 * @param limit 18136 */ 18137 function truncateChars(input, maxlength) { 18138 var text = input.val(); 18139 var newlines = 0; 18140 18141 if (options.twoCharLinebreak) { 18142 text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n'); 18143 18144 if (text.substr(text.length - 1) === '\n' && text.length % 2 === 1) { 18145 newlines = 1; 18146 } 18147 } 18148 18149 input.val(text.substr(0, maxlength - newlines)); 18150 } 18151 18152 /** 18153 * Return the length of the specified input in UTF8 encoding. 18154 * 18155 * @param input 18156 * @return {number} 18157 */ 18158 function utf8Length(string) { 18159 var utf8length = 0; 18160 for (var n = 0; n < string.length; n++) { 18161 var c = string.charCodeAt(n); 18162 if (c < 128) { 18163 utf8length++; 18164 } 18165 else if ((c > 127) && (c < 2048)) { 18166 utf8length = utf8length + 2; 18167 } 18168 else { 18169 utf8length = utf8length + 3; 18170 } 18171 } 18172 return utf8length; 18173 } 18174 18175 /** 18176 * Return true if the indicator should be showing up. 18177 * 18178 * @param input 18179 * @param thereshold 18180 * @param maxlength 18181 * @return {number} 18182 */ 18183 function charsLeftThreshold(input, thereshold, maxlength) { 18184 var output = true; 18185 if (!options.alwaysShow && (maxlength - inputLength(input) > thereshold)) { 18186 output = false;
18187 } 18188 return output; 18189 } 18190 18191 /** 18192 * Returns how many chars are left to complete the fill up of the form. 18193 * 18194 * @param input 18195 * @param maxlength 18196 * @return {number} 18197 */ 18198 function remainingChars(input, maxlength) { 18199 var length = maxlength - inputLength(input); 18200 return length; 18201 } 18202 18203 /** 18204 * When called displays the indicator. 18205 * 18206 * @param indicator 18207 */ 18208 function showRemaining(currentInput, indicator) { 18209 indicator.css({ 18210 display: 'block' 18211 }); 18212 currentInput.trigger('maxlength.shown'); 18213 } 18214 18215 /** 18216 * When called shows the indicator. 18217 * 18218 * @param indicator 18219 */ 18220 function hideRemaining(currentInput, indicator) { 18221 indicator.css({ 18222 display: 'none' 18223 }); 18224 currentInput.trigger('maxlength.hidden'); 18225 } 18226 18227 /** 18228 * This function updates the value in the indicator 18229 * 18230 * @param maxLengthThisInput 18231 * @param typedChars 18232 * @return String 18233 */ 18234 function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) { 18235 var output = ''; 18236 if (options.message) { 18237 if (typeof options.message === 'function') { 18238 output = options.message(currentInputText, maxLengthThisInput); 18239 } else { 18240 output = options.message.replace('%charsTyped%', typedChars) 18241 .replace('%charsRemaining%', maxLengthThisInput - typedChars) 18242 .replace('%charsTotal%', maxLengthThisInput); 18243 } 18244 } else { 18245 if (options.preText) { 18246 output += options.preText; 18247 } 18248 if (!options.showCharsTyped) { 18249 output += maxLengthThisInput - typedChars; 18250 } 18251 else { 18252 output += typedChars; 18253 } 18254 if (options.showMaxLength) { 18255 output += options.separator + maxLengthThisInput; 18256 } 18257 if (options.postText) { 18258 output += options.postText; 18259 } 18260 } 18261 return output; 18262 } 18263 18264 /** 18265 * This function updates the value of the counter in the indicator. 18266 * Wants as parameters: the number of remaining chars, the element currently managed, 18267 * the maxLength for the current input and the indicator generated for it. 18268 * 18269 * @param remaining 18270 * @param currentInput 18271 * @param maxLengthCurrentInput 18272 * @param maxLengthIndicator 18273 */ 18274 function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) { 18275 if (maxLengthIndicator) { 18276 maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining))); 18277 18278 if (remaining > 0) { 18279 if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) { 18280 showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass).addClass(options.warningClass)); 18281 } else { 18282 hideRemaining(currentInput, maxLengthIndicator); 18283 } 18284 } else { 18285 showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass)); 18286 } 18287 } 18288 18289 if (options.allowOverMax) { 18290 // class to use for form validation on custom maxlength attribute 18291 if (remaining < 0) { 18292 currentInput.addClass('overmax'); 18293 } else { 18294 currentInput.removeClass('overmax'); 18295 } 18296 } 18297 } 18298 18299 /**
18300 * This function returns an object containing all the 18301 * informations about the position of the current input 18302 * 18303 * @param currentInput 18304 * @return object {bottom height left right top width} 18305 * 18306 */ 18307 function getPosition(currentInput) { 18308 var el = currentInput[0]; 18309 return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : { 18310 width: el.offsetWidth, 18311 height: el.offsetHeight 18312 }, currentInput.offset()); 18313 } 18314 18315 /** 18316 * This function places the maxLengthIndicator at the 18317 * top / bottom / left / right of the currentInput 18318 * 18319 * @param currentInput 18320 * @param maxLengthIndicator 18321 * @return null 18322 * 18323 */ 18324 function place(currentInput, maxLengthIndicator) { 18325 var pos = getPosition(currentInput); 18326 18327 // Supports custom placement handler 18328 if ($.type(options.placement) === 'function'){ 18329 options.placement(currentInput, maxLengthIndicator, pos); 18330 return; 18331 } 18332 18333 // Supports custom placement via css positional properties 18334 if ($.isPlainObject(options.placement)){ 18335 placeWithCSS(options.placement, maxLengthIndicator); 18336 return; 18337 } 18338 18339 var inputOuter = currentInput.outerWidth(), 18340 outerWidth = maxLengthIndicator.outerWidth(), 18341 actualWidth = maxLengthIndicator.width(), 18342 actualHeight = maxLengthIndicator.height(); 18343 18344 // get the right position if the indicator is appended to the input's parent 18345 if (options.appendToParent) { 18346 pos.top -= currentInput.parent().offset().top; 18347 pos.left -= currentInput.parent().offset().left; 18348 } 18349 18350 switch (options.placement) { 18351 case 'bottom': 18352 maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 }); 18353 break; 18354 case 'top': 18355 maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 }); 18356 break; 18357 case 'left': 18358 maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth }); 18359 break; 18360 case 'right': 18361 maxLengthIndicator.css({ top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }); 18362 break; 18363 case 'bottom-right': 18364 maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width }); 18365 break; 18366 case 'top-right': 18367 maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter }); 18368 break; 18369 case 'top-left': 18370 maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left - outerWidth }); 18371 break; 18372 case 'bottom-left': 18373 maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left - outerWidth }); 18374 break; 18375 case 'centered-right': 18376 maxLengthIndicator.css({ top: pos.top + (actualHeight / 2), left: pos.left + inputOuter - outerWidth - 3 }); 18377 break; 18378 18379 // Some more options for placements 18380 case 'bottom-right-inside': 18381 maxLengthIndicator.css({ top: pos.top + pos.height, left: pos.left + pos.width - outerWidth }); 18382 break; 18383 case 'top-right-inside': 18384 maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left + inputOuter - outerWidth }); 18385 break; 18386 case 'top-left-inside': 18387 maxLengthIndicator.css({ top: pos.top - actualHeight, left: pos.left }); 18388 break; 18389 case 'bottom-left-inside': 18390 maxLengthIndicator.css({ top: pos.top + currentInput.outerHeight(), left: pos.left }); 18391 break; 18392 } 18393 } 18394 18395 /** 18396 * This function places the maxLengthIndicator based on placement config object. 18397 * 18398 * @param {object} placement 18399 * @param {$} maxLengthIndicator 18400 * @return null 18401 * 18402 */ 18403 function placeWithCSS(placement, maxLengthIndicator) { 18404 if (!placement || !maxLengthIndicator){ 18405 return; 18406 } 18407
18408 var POSITION_KEYS = [ 18409 'top', 18410 'bottom', 18411 'left', 18412 'right', 18413 'position' 18414 ]; 18415 18416 var cssPos = {}; 18417 18418 // filter css properties to position 18419 $.each(POSITION_KEYS, function (i, key) { 18420 var val = options.placement[key]; 18421 if (typeof val !== 'undefined'){ 18422 cssPos[key] = val; 18423 } 18424 }); 18425 18426 maxLengthIndicator.css(cssPos); 18427 18428 return; 18429 } 18430 18431 /** 18432 * This function retrieves the maximum length of currentInput 18433 * 18434 * @param currentInput 18435 * @return {number} 18436 * 18437 */ 18438 function getMaxLength(currentInput) { 18439 var attr = 'maxlength'; 18440 if (options.allowOverMax) { 18441 attr = 'data-bs-mxl'; 18442 } 18443 return currentInput.attr(attr) || currentInput.attr('size'); 18444 } 18445 18446 return this.each(function () { 18447 18448 var currentInput = $(this), 18449 maxLengthCurrentInput, 18450 maxLengthIndicator; 18451 18452 $(window).resize(function () { 18453 if (maxLengthIndicator) { 18454 place(currentInput, maxLengthIndicator); 18455 } 18456 }); 18457 18458 if (options.allowOverMax) { 18459 $(this).attr('data-bs-mxl', $(this).attr('maxlength')); 18460 $(this).removeAttr('maxlength'); 18461 } 18462 18463 function firstInit() { 18464 var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0'); 18465 maxLengthCurrentInput = getMaxLength(currentInput); 18466 18467 if (!maxLengthIndicator) { 18468 maxLengthIndicator = $('<span class="bootstrap-maxlength"></span>').css({ 18469 display: 'none', 18470 position: 'absolute', 18471 whiteSpace: 'nowrap', 18472 zIndex: 1099 18473 }).html(maxlengthContent); 18474 } 18475 18476 // We need to detect resizes if we are dealing with a textarea: 18477 if (currentInput.is('textarea')) { 18478 currentInput.data('maxlenghtsizex', currentInput.outerWidth()); 18479 currentInput.data('maxlenghtsizey', currentInput.outerHeight()); 18480 18481 currentInput.mouseup(function () { 18482 if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) { 18483 place(currentInput, maxLengthIndicator); 18484 } 18485 18486 currentInput.data('maxlenghtsizex', currentInput.outerWidth()); 18487 currentInput.data('maxlenghtsizey', currentInput.outerHeight()); 18488 }); 18489 } 18490 18491 if (options.appendToParent) { 18492 currentInput.parent().append(maxLengthIndicator); 18493 currentInput.parent().css('position', 'relative'); 18494 } else { 18495 documentBody.append(maxLengthIndicator); 18496 } 18497 18498 var remaining = remainingChars(currentInput, getMaxLength(currentInput)); 18499 manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 18500 place(currentInput, maxLengthIndicator); 18501 } 18502 18503 if (options.showOnReady) { 18504 currentInput.ready(function () { 18505 firstInit(); 18506 }); 18507 } else { 18508 currentInput.focus(function () { 18509 firstInit(); 18510 }); 18511 } 18512 18513 currentInput.on('maxlength.reposition', function () { 18514 place(currentInput, maxLengthIndicator); 18515 }); 18516 18517 18518 currentInput.on('destroyed', function () { 18519 if (maxLengthIndicator) { 18520 maxLengthIndicator.remove(); 18521 } 18522 }); 18523 18524 currentInput.on('blur', function () { 18525 if (maxLengthIndicator && !options.showOnReady) { 18526 maxLengthIndicator.remove(); 18527 } 18528 }); 18529 18530 currentInput.on('input', function () { 18531 var maxlength = getMaxLength(currentInput), 18532 remaining = remainingChars(currentInput, maxlength), 18533 output = true; 18534 18535 if (options.validate && remaining < 0) { 18536 truncateChars(currentInput, maxlength); 18537 output = false; 18538 } else { 18539 manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator); 18540 } 18541 18542 //reposition the indicator if placement "bottom-right-inside" & "top-right-inside" is used 18543 if (options.placement === 'bottom-right-inside' || options.placement === 'top-right-inside') { 18544 place(currentInput, maxLengthIndicator); 18545 } 18546 18547 return output; 18548 }); 18549 }); 18550 } 18551 }); 18552}(jQuery)); 18553 18554+function(a){"use strict";function c(c){return this.each(function(){var d=a(this),e=d.data("multiselectsplitter"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("multiselectsplitter",e=new b(this,f)),"string"==typeof c&&e[c]())})}var b=function(a,b){this.init("multiselectsplitter",a,b)};b.DEFAULTS={selectSize:null,maxSelectSize:null,clearOnFirstChange:!1,onlySameGroup:!1,groupCounter:!1,maximumSelected:null,afterInitialize:null,maximumAlert:function(a){alert("Only "+a+" values can be selected")},createFirstSelect:function(a,b){return"<option>"+a+"</option>"},createSecondSelect:function(a,b){return"<option>"+a+"</option>"},template:'<div class="row" data-multiselectsplitter-wrapper-selector><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-firstselect-selector></select></div> <!-- Add the extra clearfix for only the required viewport --><div class="col-xs-6 col-sm-6"><select class="form-control" data-multiselectsplitter-secondselect-selector></select></div></div>'},b.prototype.init=function(c,d,e){var f=this;f.type=c,f.last$ElementSelected=[],f.initialized=!1,f.$element=a(d),f.$element.hide(),f.options=a.extend({},b.DEFAULTS,e),f.$element.after(f.options.template),f.$wrapper=f.$element.next("div[data-multiselectsplitter-wrapper-selector]"),f.$firstSelect=a("select[data-multiselectsplitter-firstselect-selector]",f.$wrapper),f.$secondSelect=a("select[data-multiselectsplitter-secondselect-selector]",f.$wrapper);var g=0,h=0;if(0!=f.$element.find("optgroup").length){f.$element.find("optgroup").each(function(){var b=a(this).attr("label"),c=a(f.options.createFirstSelect(b,f.$element));c.val(b),c.attr("data-current-label",c.text()),f.$firstSelect.append(c);var d=a(this).find("option").length;d>h&&(h=d),g++});var i=Math.max(g,h);i=Math.min(i,10),f.options.selectSize?i=f.options.selectSize:f.options.maxSelectSize&&(i=Math.min(i,f.options.maxSelectSize)),f.$firstSelect.attr("size",i),f.$secondSelect.attr("size",i),f.$element.attr("multiple")&&f.$secondSelect.attr("multiple","multiple"),f.$element.is(":disabled")&&f.disable(),f.$firstSelect.on("change",a.proxy(f.updateParentCategory,f)),f.$secondSelect.on("click change",a.proxy(f.updateChildCategory,f)),f.update=function(){if(!(f.$element.find("option").length<1)){var b,a=f.$element.find("option:selected:first");b=a.length?a.parent().attr("label"):f.$element.find("option:first").parent().attr("label"),f.$firstSelect.find('option[value="'+b+'"]').prop("selected",!0),f.$firstSelect.trigger("change")}}
18554,f.update(),f.initialized=!0,f.options.afterInitialize&&f.options.afterInitialize(f.$firstSelect,f.$secondSelect)}},b.prototype.disable=function(){this.$secondSelect.prop("disabled",!0),this.$firstSelect.prop("disabled",!0)},b.prototype.enable=function(){this.$secondSelect.prop("disabled",!1),this.$firstSelect.prop("disabled",!1)},b.prototype.createSecondSelect=function(){var b=this;b.$secondSelect.empty(),a.each(b.$element.find('optgroup[label="'+b.$firstSelect.val()+'"] option'),function(c,d){var e=a(this).val(),f=a(this).text(),g=a(b.options.createSecondSelect(f,b.$firstSelect));g.val(e),a.each(b.$element.find("option:selected"),function(b,c){a(c).val()==e&&g.prop("selected",!0)}),b.$secondSelect.append(g)})},b.prototype.updateParentCategory=function(){var a=this;a.last$ElementSelected=a.$element.find("option:selected"),a.options.clearOnFirstChange&&a.initialized&&a.$element.find("option:selected").prop("selected",!1),a.createSecondSelect(),a.checkSelected(),a.updateCounter()},b.prototype.updateCounter=function(){var b=this;b.$element.attr("multiple")&&b.options.groupCounter&&a.each(b.$firstSelect.find("option"),function(c,d){var e=a(d).val(),f=a(d).data("currentLabel"),g=b.$element.find('optgroup[label="'+e+'"] option:selected').length;g>0&&(f+=" ("+g+")"),a(d).html(f)})},b.prototype.checkSelected=function(){var b=this;if(b.$element.attr("multiple")&&b.options.maximumSelected){var c=0;if(c="function"==typeof b.options.maximumSelected?b.options.maximumSelected(b.$firstSelect,b.$secondSelect):b.options.maximumSelected,!(c<1)){var d=b.$element.find("option:selected");if(d.length>c){b.$firstSelect.find("option:selected").prop("selected",!1),b.$secondSelect.find("option:selected").prop("selected",!1),b.initialized?(b.$element.find("option:selected").prop("selected",!1),b.last$ElementSelected.prop("selected",!0)):a.each(b.$element.find("option:selected"),function(b,d){b>c-1&&a(d).prop("selected",!1)});var e=b.last$ElementSelected.first().parent().attr("label");b.$firstSelect.find('option[value="'+e+'"]').prop("selected",!0),b.createSecondSelect(),b.options.maximumAlert(c)}}}},b.prototype.basicUpdateChildCategory=function(b,c){var d=this;d.last$ElementSelected=d.$element.find("option:selected");var e=d.$secondSelect.val();a.isArray(e)||(e=[e]);var f=d.$firstSelect.val(),g=!1;d.$element.attr("multiple")?d.options.onlySameGroup?a.each(d.$element.find("option:selected"),function(b,c){if(a(c).parent().attr("label")!=f)return g=!0,!1}):c||(g=!0):g=!0,g?d.$element.find("option:selected").prop("selected",!1):a.each(d.$element.find("option:selected"),function(b,c){f==a(c).parent().attr("label")&&a.inArray(a(c).val(),e)==-1&&a(c).prop("selected",!1)}),a.each(e,function(a,b){d.$element.find('option[value="'+b+'"]').prop("selected",!0)}),d.checkSelected(),d.updateCounter(),d.$element.trigger("change")},b.prototype.updateChildCategory=function(b){"change"==b.type?this.timeOut=setTimeout(a.proxy(function(){this.basicUpdateChildCategory(b,b.ctrlKey)},this),10):"click"==b.type&&(clearTimeout(this.timeOut),this.basicUpdateChildCategory(b,b.ctrlKey))},b.prototype.destroy=function(){this.$wrapper.remove(),this.$element.removeData(this.type),this.$element.show()},a.fn.multiselectsplitter=c,a.fn.multiselectsplitter.Constructor=b,a.fn.multiselectsplitter.VERSION="1.0.1"}(jQuery); 18555/*! 18556 * Bootstrap-select v1.13.5 (https://developer.snapappointments.com/bootstrap-select) 18557 * 18558 * Copyright 2012-2018 SnapAppointments, LLC 18559 * Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) 18560 */ 18561 18562(function (root, factory) { 18563 if (root === undefined && window !== undefined) root = window; 18564 if (typeof define === 'function' && define.amd) { 18565 // AMD. Register as an anonymous module unless amdModuleId is set 18566 define(["jquery"], function (a0) { 18567 return (factory(a0)); 18568 }); 18569 } else if (typeof module === 'object' && module.exports) { 18570 // Node. Does not work with strict CommonJS, but 18571 // only CommonJS-like environments that support module.exports, 18572 // like Node. 18573 module.exports = factory(require("jquery")); 18574 } else { 18575 factory(root["jQuery"]); 18576 } 18577}(this, function (jQuery) { 18578 18579(function ($) { 18580 'use strict'; 18581 18582 // Polyfill for browsers with no classList support 18583 // Remove in v2 18584 if (!('classList' in document.createElement('_'))) { 18585 (function (view) { 18586 if (!('Element' in view)) return; 18587 18588 var classListProp = 'classList', 18589 protoProp = 'prototype', 18590 elemCtrProto = view.Element[protoProp], 18591 objCtr = Object, 18592 classListGetter = function () { 18593 var $elem = $(this); 18594 18595 return { 18596 add: function (classes) {
vendor: 13,858 bytes, lines 18597-19045
18597 return $elem.addClass(classes); 18598 }, 18599 remove: function (classes) { 18600 return $elem.removeClass(classes); 18601 }, 18602 toggle: function (classes, force) { 18603 return $elem.toggleClass(classes, force); 18604 }, 18605 contains: function (classes) { 18606 return $elem.hasClass(classes); 18607 } 18608 } 18609 }; 18610 18611 if (objCtr.defineProperty) { 18612 var classListPropDesc = { 18613 get: classListGetter, 18614 enumerable: true, 18615 configurable: true 18616 }; 18617 try { 18618 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 18619 } catch (ex) { // IE 8 doesn't support enumerable:true 18620 // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36 18621 // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected 18622 if (ex.number === undefined || ex.number === -0x7FF5EC54) { 18623 classListPropDesc.enumerable = false; 18624 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 18625 } 18626 } 18627 } else if (objCtr[protoProp].__defineGetter__) { 18628 elemCtrProto.__defineGetter__(classListProp, classListGetter); 18629 } 18630 }(window)); 18631 } 18632 18633 var testElement = document.createElement('_'); 18634 18635 testElement.classList.toggle('c3', false); 18636 18637 // Polyfill for IE 10 and Firefox <24, where classList.toggle does not 18638 // support the second argument. 18639 if (testElement.classList.contains('c3')) { 18640 var _toggle = DOMTokenList.prototype.toggle; 18641 18642 DOMTokenList.prototype.toggle = function (token, force) { 18643 if (1 in arguments && !this.contains(token) === !force) { 18644 return force; 18645 } else { 18646 return _toggle.call(this, token); 18647 } 18648 }; 18649 } 18650 18651 testElement = null; 18652 18653 // shallow array comparison 18654 function isEqual (array1, array2) { 18655 return array1.length === array2.length && array1.every(function (element, index) { 18656 return element === array2[index]; 18657 }); 18658 }; 18659 18660 // <editor-fold desc="Shims"> 18661 if (!String.prototype.startsWith) { 18662 (function () { 18663 'use strict'; // needed to support `apply`/`call` with `undefined`/`null` 18664 var defineProperty = (function () { 18665 // IE 8 only supports `Object.defineProperty` on DOM elements 18666 try { 18667 var object = {}; 18668 var $defineProperty = Object.defineProperty; 18669 var result = $defineProperty(object, object, object) && $defineProperty; 18670 } catch (error) { 18671 } 18672 return result; 18673 }()); 18674 var toString = {}.toString; 18675 var startsWith = function (search) { 18676 if (this == null) { 18677 throw new TypeError(); 18678 } 18679 var string = String(this); 18680 if (search && toString.call(search) == '[object RegExp]') { 18681 throw new TypeError(); 18682 } 18683 var stringLength = string.length; 18684 var searchString = String(search); 18685 var searchLength = searchString.length; 18686 var position = arguments.length > 1 ? arguments[1] : undefined; 18687 // `ToInteger` 18688 var pos = position ? Number(position) : 0; 18689 if (pos != pos) { // better `isNaN` 18690 pos = 0; 18691 } 18692 var start = Math.min(Math.max(pos, 0), stringLength); 18693 // Avoid the `indexOf` call if no match is possible 18694 if (searchLength + start > stringLength) { 18695 return false; 18696 } 18697 var index = -1; 18698 while (++index < searchLength) { 18699 if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) { 18700 return false; 18701 } 18702 } 18703 return true; 18704 }; 18705 if (defineProperty) { 18706 defineProperty(String.prototype, 'startsWith', { 18707 'value': startsWith, 18708 'configurable': true, 18709 'writable': true 18710 }); 18711 } else { 18712 String.prototype.startsWith = startsWith; 18713 } 18714 }()); 18715 } 18716 18717 if (!Object.keys) { 18718 Object.keys = function ( 18719 o, // object 18720 k, // key 18721 r // result array 18722 ) { 18723 // initialize object and result 18724 r = []; 18725 // iterate over object keys 18726 for (k in o) { 18727 // fill result array with non-prototypical keys 18728 r.hasOwnProperty.call(o, k) && r.push(k); 18729 } 18730 // return result 18731 return r; 18732 }; 18733 } 18734 18735 // much faster than $.val() 18736 function getSelectValues (select) { 18737 var result = []; 18738 var options = select && select.options; 18739 var opt; 18740 18741 if (select.multiple) { 18742 for (var i = 0, len = options.length; i < len; i++) { 18743 opt = options[i]; 18744 18745 if (opt.selected) { 18746 result.push(opt.value || opt.text); 18747 } 18748 } 18749 } else { 18750 result = select.value; 18751 } 18752 18753 return result; 18754 } 18755 18756 // set data-selected on select element if the value has been programmatically selected 18757 // prior to initialization of bootstrap-select 18758 // * consider removing or replacing an alternative method * 18759 var valHooks = { 18760 useDefault: false, 18761 _set: $.valHooks.select.set 18762 }; 18763 18764 $.valHooks.select.set = function (elem, value) { 18765 if (value && !valHooks.useDefault) $(elem).data('selected', true); 18766 18767 return valHooks._set.apply(this, arguments); 18768 }; 18769 18770 var changedArguments = null; 18771 18772 var EventIsSupported = (function () { 18773 try { 18774 new Event('change'); 18775 return true; 18776 } catch (e) { 18777 return false; 18778 } 18779 })(); 18780 18781 $.fn.triggerNative = function (eventName) { 18782 var el = this[0], 18783 event; 18784 18785 if (el.dispatchEvent) { // for modern browsers & IE9+ 18786 if (EventIsSupported) { 18787 // For modern browsers 18788 event = new Event(eventName, { 18789 bubbles: true 18790 }); 18791 } else { 18792 // For IE since it doesn't support Event constructor 18793 event = document.createEvent('Event'); 18794 event.initEvent(eventName, true, false); 18795 } 18796 18797 el.dispatchEvent(event); 18798 } else if (el.fireEvent) { // for IE8 18799 event = document.createEventObject(); 18800 event.eventType = eventName; 18801 el.fireEvent('on' + eventName, event); 18802 } else { 18803 // fall back to jQuery.trigger 18804 this.trigger(eventName); 18805 } 18806 }; 18807 // </editor-fold> 18808 18809 function stringSearch (li, searchString, method, normalize) { 18810 var stringTypes = [ 18811 'content', 18812 'subtext', 18813 'tokens' 18814 ], 18815 searchSuccess = false; 18816 18817 for (var i = 0; i < stringTypes.length; i++) { 18818 var stringType = stringTypes[i], 18819 string = li[stringType]; 18820 18821 if (string) { 18822 string = string.toString(); 18823 18824 // Strip HTML tags. This isn't perfect, but it's much faster than any other method 18825 if (stringType === 'content') { 18826 string = string.replace(/<[^>]+>/g, ''); 18827 } 18828 18829 if (normalize) string = normalizeToBase(string); 18830 string = string.toUpperCase(); 18831 18832 if (method === 'contains') { 18833 searchSuccess = string.indexOf(searchString) >= 0; 18834 } else { 18835 searchSuccess = string.startsWith(searchString); 18836 } 18837 18838 if (searchSuccess) break; 18839 } 18840 } 18841 18842 return searchSuccess; 18843 } 18844 18845 function toInteger (value) { 18846 return parseInt(value, 10) || 0; 18847 } 18848 18849 // Borrowed from Lodash (_.deburr) 18850 /** Used to map Latin Unicode letters to basic Latin letters. */ 18851 var deburredLetters = { 18852 // Latin-1 Supplement block. 18853 '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', 18854 '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', 18855 '\xc7': 'C', '\xe7': 'c', 18856 '\xd0': 'D', '\xf0': 'd', 18857 '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', 18858 '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', 18859 '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', 18860 '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', 18861 '\xd1': 'N', '\xf1': 'n', 18862 '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', 18863 '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', 18864 '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', 18865 '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', 18866 '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', 18867 '\xc6': 'Ae', '\xe6': 'ae', 18868 '\xde': 'Th', '\xfe': 'th', 18869 '\xdf': 'ss', 18870 // Latin Extended-A block. 18871 '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', 18872 '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', 18873 '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', 18874 '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', 18875 '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', 18876 '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', 18877 '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', 18878 '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', 18879 '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', 18880 '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', 18881 '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', 18882 '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', 18883 '\u0134': 'J', '\u0135': 'j', 18884 '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', 18885 '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', 18886 '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', 18887 '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', 18888 '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', 18889 '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', 18890 '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', 18891 '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', 18892 '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', 18893 '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', 18894 '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', 18895 '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', 18896 '\u0163': 't', '\u0165': 't', '\u0167': 't', 18897 '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', 18898 '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', 18899 '\u0174': 'W', '\u0175': 'w', 18900 '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', 18901 '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', 18902 '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', 18903 '\u0132': 'IJ', '\u0133': 'ij', 18904 '\u0152': 'Oe', '\u0153': 'oe', 18905 '\u0149': "'n", '\u017f': 's' 18906 }; 18907 18908 /** Used to match Latin Unicode letters (excluding mathematical operators). */ 18909 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; 18910 18911 /** Used to compose unicode character classes. */ 18912 var rsComboMarksRange = '\\u0300-\\u036f', 18913 reComboHalfMarksRange = '\\ufe20-\\ufe2f', 18914 rsComboSymbolsRange = '\\u20d0-\\u20ff', 18915 rsComboMarksExtendedRange = '\\u1ab0-\\u1aff', 18916 rsComboMarksSupplementRange = '\\u1dc0-\\u1dff', 18917 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange + rsComboMarksExtendedRange + rsComboMarksSupplementRange; 18918 18919 /** Used to compose unicode capture groups. */ 18920 var rsCombo = '[' + rsComboRange + ']'; 18921 18922 /** 18923 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and 18924 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). 18925 */ 18926 var reComboMark = RegExp(rsCombo, 'g'); 18927 18928 function deburrLetter (key) { 18929 return deburredLetters[key]; 18930 }; 18931 18932 function normalizeToBase (string) { 18933 string = string.toString(); 18934 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); 18935 } 18936 18937 // List of HTML entities for escaping. 18938 var escapeMap = { 18939 '&': '&', 18940 '<': '<', 18941 '>': '>', 18942 '"': '"', 18943 "'": ''', 18944 '`': '`' 18945 }; 18946 18947 var unescapeMap = { 18948 '&': '&', 18949 '<': '<', 18950 '>': '>', 18951 '"': '"', 18952 ''': "'", 18953 '`': '`' 18954 }; 18955 18956 // Functions for escaping and unescaping strings to/from HTML interpolation. 18957 var createEscaper = function (map) { 18958 var escaper = function (match) { 18959 return map[match]; 18960 }; 18961 // Regexes for identifying a key that needs to be escaped. 18962 var source = '(?:' + Object.keys(map).join('|') + ')'; 18963 var testRegexp = RegExp(source); 18964 var replaceRegexp = RegExp(source, 'g'); 18965 return function (string) { 18966 string = string == null ? '' : '' + string; 18967 return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; 18968 }; 18969 }; 18970 18971 var htmlEscape = createEscaper(escapeMap); 18972 var htmlUnescape = createEscaper(unescapeMap); 18973 18974 /** 18975 * ------------------------------------------------------------------------ 18976 * Constants 18977 * ------------------------------------------------------------------------ 18978 */ 18979 18980 var keyCodeMap = { 18981 32: ' ', 18982 48: '0', 18983 49: '1', 18984 50: '2', 18985 51: '3', 18986 52: '4', 18987 53: '5', 18988 54: '6', 18989 55: '7', 18990 56: '8', 18991 57: '9', 18992 59: ';', 18993 65: 'A', 18994 66: 'B', 18995 67: 'C', 18996 68: 'D', 18997 69: 'E', 18998 70: 'F', 18999 71: 'G', 19000 72: 'H', 19001 73: 'I', 19002 74: 'J', 19003 75: 'K', 19004 76: 'L', 19005 77: 'M', 19006 78: 'N', 19007 79: 'O', 19008 80: 'P', 19009 81: 'Q', 19010 82: 'R', 19011 83: 'S', 19012 84: 'T', 19013 85: 'U', 19014 86: 'V', 19015 87: 'W', 19016 88: 'X', 19017 89: 'Y', 19018 90: 'Z', 19019 96: '0', 19020 97: '1', 19021 98: '2', 19022 99: '3', 19023 100: '4', 19024 101: '5', 19025 102: '6', 19026 103: '7', 19027 104: '8', 19028 105: '9' 19029 }; 19030 19031 var keyCodes = { 19032 ESCAPE: 27, // KeyboardEvent.which value for Escape (Esc) key 19033 ENTER: 13, // KeyboardEvent.which value for Enter key 19034 SPACE: 32, // KeyboardEvent.which value for space key 19035 TAB: 9, // KeyboardEvent.which value for tab key 19036 ARROW_UP: 38, // KeyboardEvent.which value for up arrow key 19037 ARROW_DOWN: 40 // KeyboardEvent.which value for down arrow key 19038 } 19039 19040 var version = { 19041 success: false, 19042 major: '3' 19043 }; 19044 19045 try {
19046 version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.'); 19047 version.major = version.full[0]; 19048 version.success = true; 19049 } catch (err) { 19050 console.warn( 19051 'There was an issue retrieving Bootstrap\'s version. ' + 19052 'Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision. ' + 19053 'If loading Bootstrap asynchronously, the version may need to be manually specified via $.fn.selectpicker.Constructor.BootstrapVersion.', 19054 err 19055 ); 19056 } 19057 19058 var selectId = 0; 19059 19060 var EVENT_KEY = '.bs.select'; 19061 19062 var classNames = { 19063 DISABLED: 'disabled', 19064 DIVIDER: 'divider', 19065 SHOW: 'open', 19066 DROPUP: 'dropup', 19067 MENU: 'dropdown-menu', 19068 MENURIGHT: 'dropdown-menu-right', 19069 MENULEFT: 'dropdown-menu-left', 19070 // to-do: replace with more advanced template/customization options 19071 BUTTONCLASS: 'btn-default', 19072 POPOVERHEADER: 'popover-title' 19073 } 19074 19075 var Selector = { 19076 MENU: '.' + classNames.MENU 19077 } 19078 19079 if (version.major === '4') { 19080 classNames.DIVIDER = 'dropdown-divider'; 19081 classNames.SHOW = 'show'; 19082 classNames.BUTTONCLASS = 'btn-light'; 19083 classNames.POPOVERHEADER = 'popover-header'; 19084 } 19085 19086 var REGEXP_ARROW = new RegExp(keyCodes.ARROW_UP + '|' + keyCodes.ARROW_DOWN); 19087 var REGEXP_TAB_OR_ESCAPE = new RegExp('^' + keyCodes.TAB + '$|' + keyCodes.ESCAPE); 19088 19089 var Selectpicker = function (element, options) { 19090 var that = this; 19091 19092 // bootstrap-select has been initialized - revert valHooks.select.set back to its original function 19093 if (!valHooks.useDefault) { 19094 $.valHooks.select.set = valHooks._set; 19095 valHooks.useDefault = true; 19096 } 19097 19098 this.$element = $(element); 19099 this.$newElement = null; 19100 this.$button = null; 19101 this.$menu = null; 19102 this.options = options; 19103 this.selectpicker = { 19104 main: { 19105 // store originalIndex (key) and newIndex (value) in this.selectpicker.main.map.newIndex for fast accessibility 19106 // allows us to do this.main.elements[this.selectpicker.main.map.newIndex[index]] to select an element based on the originalIndex 19107 map: { 19108 newIndex: {}, 19109 originalIndex: {} 19110 } 19111 }, 19112 current: { 19113 map: {} 19114 }, // current changes if a search is in progress 19115 search: { 19116 map: {} 19117 }, 19118 view: {}, 19119 keydown: { 19120 keyHistory: '', 19121 resetKeyHistory: { 19122 start: function () { 19123 return setTimeout(function () { 19124 that.selectpicker.keydown.keyHistory = ''; 19125 }, 800); 19126 } 19127 } 19128 } 19129 }; 19130 // If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a 19131 // data-attribute) 19132 if (this.options.title === null) { 19133 this.options.title = this.$element.attr('title'); 19134 } 19135 19136 // Format window padding 19137 var winPad = this.options.windowPadding; 19138 if (typeof winPad === 'number') { 19139 this.options.windowPadding = [winPad, winPad, winPad, winPad]; 19140 } 19141 19142 // Expose public methods 19143 this.val = Selectpicker.prototype.val; 19144 this.render = Selectpicker.prototype.render; 19145 this.refresh = Selectpicker.prototype.refresh; 19146 this.setStyle = Selectpicker.prototype.setStyle; 19147 this.selectAll = Selectpicker.prototype.selectAll; 19148 this.deselectAll = Selectpicker.prototype.deselectAll; 19149 this.destroy = Selectpicker.prototype.destroy; 19150 this.remove = Selectpicker.prototype.remove; 19151 this.show = Selectpicker.prototype.show; 19152 this.hide = Selectpicker.prototype.hide; 19153 19154 this.init(); 19155 }; 19156 19157 Selectpicker.VERSION = '1.13.5'; 19158 19159 Selectpicker.BootstrapVersion = version.major; 19160 19161 // part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both. 19162 Selectpicker.DEFAULTS = { 19163 noneSelectedText: 'Nothing selected', 19164 noneResultsText: 'No results matched {0}', 19165 countSelectedText: function (numSelected, numTotal) { 19166 return (numSelected == 1) ? '{0} item selected' : '{0} items selected'; 19167 }, 19168 maxOptionsText: function (numAll, numGroup) { 19169 return [ 19170 (numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)', 19171 (numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)' 19172 ]; 19173 }, 19174 selectAllText: 'Select All', 19175 deselectAllText: 'Deselect All',
vendor: 8,238 bytes, lines 19176-19418
19176 doneButton: false, 19177 doneButtonText: 'Close', 19178 multipleSeparator: ', ', 19179 styleBase: 'btn', 19180 style: classNames.BUTTONCLASS, 19181 size: 'auto', 19182 title: null, 19183 selectedTextFormat: 'values', 19184 width: false, 19185 container: false, 19186 hideDisabled: false, 19187 showSubtext: false, 19188 showIcon: true, 19189 showContent: true, 19190 dropupAuto: true, 19191 header: false, 19192 liveSearch: false, 19193 liveSearchPlaceholder: null, 19194 liveSearchNormalize: false, 19195 liveSearchStyle: 'contains', 19196 actionsBox: false, 19197 iconBase: 'glyphicon', 19198 tickIcon: 'glyphicon-ok', 19199 showTick: false, 19200 template: { 19201 caret: '<span class="caret"></span>' 19202 }, 19203 maxOptions: false, 19204 mobile: false, 19205 selectOnTab: false, 19206 dropdownAlignRight: false, 19207 windowPadding: 0, 19208 virtualScroll: 600, 19209 display: false 19210 }; 19211 19212 if (version.major === '4') { 19213 Selectpicker.DEFAULTS.style = 'btn-light'; 19214 Selectpicker.DEFAULTS.iconBase = ''; 19215 Selectpicker.DEFAULTS.tickIcon = 'bs-ok-default'; 19216 } 19217 19218 Selectpicker.prototype = { 19219 19220 constructor: Selectpicker, 19221 19222 init: function () { 19223 var that = this, 19224 id = this.$element.attr('id'); 19225 19226 this.selectId = selectId++; 19227 19228 this.$element.addClass('bs-select-hidden'); 19229 19230 this.multiple = this.$element.prop('multiple'); 19231 this.autofocus = this.$element.prop('autofocus'); 19232 this.$newElement = this.createDropdown(); 19233 this.createLi(); 19234 this.$element 19235 .after(this.$newElement) 19236 .prependTo(this.$newElement); 19237 this.$button = this.$newElement.children('button'); 19238 this.$menu = this.$newElement.children(Selector.MENU); 19239 this.$menuInner = this.$menu.children('.inner'); 19240 this.$searchbox = this.$menu.find('input'); 19241 19242 this.$element.removeClass('bs-select-hidden'); 19243 19244 if (this.options.dropdownAlignRight === true) this.$menu.addClass(classNames.MENURIGHT); 19245 19246 if (typeof id !== 'undefined') { 19247 this.$button.attr('data-id', id); 19248 } 19249 19250 this.checkDisabled(); 19251 this.clickListener(); 19252 if (this.options.liveSearch) this.liveSearchListener(); 19253 this.render(); 19254 this.setStyle(); 19255 this.setWidth(); 19256 if (this.options.container) { 19257 this.selectPosition(); 19258 } else { 19259 this.$element.on('hide' + EVENT_KEY, function () { 19260 if (that.isVirtual()) { 19261 // empty menu on close 19262 var menuInner = that.$menuInner[0], 19263 emptyMenu = menuInner.firstChild.cloneNode(false); 19264 19265 // replace the existing UL with an empty one - this is faster than $.empty() or innerHTML = '' 19266 menuInner.replaceChild(emptyMenu, menuInner.firstChild); 19267 menuInner.scrollTop = 0; 19268 } 19269 }); 19270 } 19271 this.$menu.data('this', this); 19272 this.$newElement.data('this', this); 19273 if (this.options.mobile) this.mobile(); 19274 19275 this.$newElement.on({ 19276 'hide.bs.dropdown': function (e) { 19277 that.$menuInner.attr('aria-expanded', false); 19278 that.$element.trigger('hide' + EVENT_KEY, e); 19279 }, 19280 'hidden.bs.dropdown': function (e) { 19281 that.$element.trigger('hidden' + EVENT_KEY, e); 19282 }, 19283 'show.bs.dropdown': function (e) { 19284 that.$menuInner.attr('aria-expanded', true); 19285 that.$element.trigger('show' + EVENT_KEY, e); 19286 }, 19287 'shown.bs.dropdown': function (e) { 19288 that.$element.trigger('shown' + EVENT_KEY, e); 19289 } 19290 }); 19291 19292 if (that.$element[0].hasAttribute('required')) { 19293 this.$element.on('invalid', function () { 19294 that.$button.addClass('bs-invalid'); 19295 19296 that.$element 19297 .on('shown' + EVENT_KEY + '.invalid', function () { 19298 that.$element 19299 .val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened 19300 .off('shown' + EVENT_KEY + '.invalid'); 19301 }) 19302 .on('rendered' + EVENT_KEY, function () { 19303 // if select is no longer invalid, remove the bs-invalid class 19304 if (this.validity.valid) that.$button.removeClass('bs-invalid'); 19305 that.$element.off('rendered' + EVENT_KEY); 19306 }); 19307 19308 that.$button.on('blur' + EVENT_KEY, function () { 19309 that.$element.focus().blur(); 19310 that.$button.off('blur' + EVENT_KEY); 19311 }); 19312 }); 19313 } 19314 19315 setTimeout(function () { 19316 that.$element.trigger('loaded' + EVENT_KEY); 19317 }); 19318 }, 19319 19320 createDropdown: function () { 19321 // Options 19322 // If we are multiple or showTick option is set, then add the show-tick class 19323 var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '', 19324 autofocus = this.autofocus ? ' autofocus' : ''; 19325 19326 // Elements 19327 var drop, 19328 header = '', 19329 searchbox = '', 19330 actionsbox = '', 19331 donebutton = ''; 19332 19333 if (this.options.header) { 19334 header = 19335 '<div class="' + classNames.POPOVERHEADER + '">' + 19336 '<button type="button" class="close" aria-hidden="true">×</button>' + 19337 this.options.header + 19338 '</div>'; 19339 } 19340 19341 if (this.options.liveSearch) { 19342 searchbox = 19343 '<div class="bs-searchbox">' + 19344 '<input type="text" class="form-control" autocomplete="off"' + 19345 ( 19346 this.options.liveSearchPlaceholder === null ? '' 19347 : 19348 ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"' 19349 ) + 19350 ' role="textbox" aria-label="Search">' + 19351 '</div>'; 19352 } 19353 19354 if (this.multiple && this.options.actionsBox) { 19355 actionsbox = 19356 '<div class="bs-actionsbox">' + 19357 '<div class="btn-group btn-group-sm btn-block">' + 19358 '<button type="button" class="actions-btn bs-select-all btn ' + classNames.BUTTONCLASS + '">' + 19359 this.options.selectAllText + 19360 '</button>' + 19361 '<button type="button" class="actions-btn bs-deselect-all btn ' + classNames.BUTTONCLASS + '">' + 19362 this.options.deselectAllText + 19363 '</button>' + 19364 '</div>' + 19365 '</div>'; 19366 } 19367 19368 if (this.multiple && this.options.doneButton) { 19369 donebutton = 19370 '<div class="bs-donebutton">' + 19371 '<div class="btn-group btn-block">' + 19372 '<button type="button" class="btn btn-sm ' + classNames.BUTTONCLASS + '">' + 19373 this.options.doneButtonText + 19374 '</button>' + 19375 '</div>' + 19376 '</div>'; 19377 } 19378 19379 drop = 19380 '<div class="dropdown bootstrap-select' + showTick + '">' + 19381 '<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" ' + (this.options.display === 'static' ? 'data-display="static"' : '') + 'data-toggle="dropdown"' + autofocus + ' role="button">' + 19382 '<div class="filter-option">' + 19383 '<div class="filter-option-inner">' + 19384 '<div class="filter-option-inner-inner"></div>' + 19385 '</div> ' + 19386 '</div>' + 19387 ( 19388 version.major === '4' ? '' 19389 : 19390 '<span class="bs-caret">' + 19391 this.options.template.caret + 19392 '</span>' 19393 ) + 19394 '</button>' + 19395 '<div class="' + classNames.MENU + ' ' + (version.major === '4' ? '' : classNames.SHOW) + '" role="combobox">' + 19396 header + 19397 searchbox + 19398 actionsbox + 19399 '<div class="inner ' + classNames.SHOW + '" role="listbox" aria-expanded="false" tabindex="-1">' + 19400 '<ul class="' + classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : '') + '">' + 19401 '</ul>' + 19402 '</div>' + 19403 donebutton + 19404 '</div>' + 19405 '</div>'; 19406 19407 return $(drop); 19408 }, 19409 19410 setPositionData: function () { 19411 this.selectpicker.view.canHighlight = []; 19412 19413 for (var i = 0; i < this.selectpicker.current.data.length; i++) { 19414 var li = this.selectpicker.current.data[i], 19415 canHighlight = true; 19416 19417 if (li.type === 'divider') { 19418 canHighlight = false;
19419 li.height = this.sizeInfo.dividerHeight; 19420 } else if (li.type === 'optgroup-label') { 19421 canHighlight = false; 19422 li.height = this.sizeInfo.dropdownHeaderHeight; 19423 } else { 19424 li.height = this.sizeInfo.liHeight; 19425 } 19426 19427 if (li.disabled) canHighlight = false; 19428 19429 this.selectpicker.view.canHighlight.push(canHighlight); 19430 19431 li.position = (i === 0 ? 0 : this.selectpicker.current.data[i - 1].position) + li.height; 19432 } 19433 }, 19434 19435 isVirtual: function () { 19436 return (this.options.virtualScroll !== false) && (this.selectpicker.main.elements.length >= this.options.virtualScroll) || this.options.virtualScroll === true; 19437 }, 19438 19439 createView: function (isSearching, scrollTop) { 19440 scrollTop = scrollTop || 0; 19441 19442 var that = this; 19443 19444 this.selectpicker.current = isSearching ? this.selectpicker.search : this.selectpicker.main; 19445 19446 var active = []; 19447 var selected; 19448 var prevActive; 19449 19450 this.setPositionData(); 19451 19452 scroll(scrollTop, true); 19453 19454 this.$menuInner.off('scroll.createView').on('scroll.createView', function (e, updateValue) { 19455 if (!that.noScroll) scroll(this.scrollTop, updateValue); 19456 that.noScroll = false; 19457 }); 19458 19459 function scroll (scrollTop, init) { 19460 var size = that.selectpicker.current.elements.length, 19461 chunks = [], 19462 chunkSize, 19463 chunkCount, 19464 firstChunk, 19465 lastChunk, 19466 currentChunk, 19467 prevPositions, 19468 positionIsDifferent, 19469 previousElements, 19470 menuIsDifferent = true, 19471 isVirtual = that.isVirtual(); 19472 19473 that.selectpicker.view.scrollTop = scrollTop; 19474 19475 if (isVirtual === true) { 19476 // if an option that is encountered that is wider than the current menu width, update the menu width accordingly 19477 if (that.sizeInfo.hasScrollBar && that.$menu[0].offsetWidth > that.sizeInfo.totalMenuWidth) { 19478 that.sizeInfo.menuWidth = that.$menu[0].offsetWidth; 19479 that.sizeInfo.totalMenuWidth = that.sizeInfo.menuWidth + that.sizeInfo.scrollBarWidth; 19480 that.$menu.css('min-width', that.sizeInfo.menuWidth); 19481 } 19482 } 19483 19484 chunkSize = Math.ceil(that.sizeInfo.menuInnerHeight / that.sizeInfo.liHeight * 1.5); // number of options in a chunk 19485 chunkCount = Math.round(size / chunkSize) || 1; // number of chunks 19486 19487 for (var i = 0; i < chunkCount; i++) { 19488 var endOfChunk = (i + 1) * chunkSize; 19489 19490 if (i === chunkCount - 1) { 19491 endOfChunk = size; 19492 } 19493 19494 chunks[i] = [ 19495 (i) * chunkSize + (!i ? 0 : 1), 19496 endOfChunk 19497 ]; 19498 19499 if (!size) break; 19500 19501 if (currentChunk === undefined && scrollTop <= that.selectpicker.current.data[endOfChunk - 1].position - that.sizeInfo.menuInnerHeight) { 19502 currentChunk = i; 19503 } 19504 } 19505 19506 if (currentChunk === undefined) currentChunk = 0; 19507 19508 prevPositions = [that.selectpicker.view.position0, that.selectpicker.view.position1]; 19509 19510 // always display previous, current, and next chunks 19511 firstChunk = Math.max(0, currentChunk - 1); 19512 lastChunk = Math.min(chunkCount - 1, currentChunk + 1); 19513 19514 that.selectpicker.view.position0 = Math.max(0, chunks[firstChunk][0]) || 0; 19515 that.selectpicker.view.position1 = Math.min(size, chunks[lastChunk][1]) || 0; 19516 19517 positionIsDifferent = prevPositions[0] !== that.selectpicker.view.position0 || prevPositions[1] !== that.selectpicker.view.position1; 19518 19519 if (that.activeIndex !== undefined) { 19520 prevActive = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.prevActiveIndex]]; 19521 active = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.activeIndex]]; 19522 selected = that.selectpicker.current.elements[that.selectpicker.current.map.newIndex[that.selectedIndex]]; 19523 19524 if (init) { 19525 if (that.activeIndex !== that.selectedIndex) { 19526 active.classList.remove('active'); 19527 if (active.firstChild) active.firstChild.classList.remove('active'); 19528 } 19529 that.activeIndex = undefined; 19530 } 19531
19532 if (that.activeIndex && that.activeIndex !== that.selectedIndex && selected && selected.length) { 19533 selected.classList.remove('active'); 19534 if (selected.firstChild) selected.firstChild.classList.remove('active'); 19535 } 19536 } 19537 19538 if (that.prevActiveIndex !== undefined && that.prevActiveIndex !== that.activeIndex && that.prevActiveIndex !== that.selectedIndex && prevActive && prevActive.length) { 19539 prevActive.classList.remove('active'); 19540 if (prevActive.firstChild) prevActive.firstChild.classList.remove('active'); 19541 } 19542 19543 if (init || positionIsDifferent) { 19544 previousElements = that.selectpicker.view.visibleElements ? that.selectpicker.view.visibleElements.slice() : []; 19545 19546 that.selectpicker.view.visibleElements = that.selectpicker.current.elements.slice(that.selectpicker.view.position0, that.selectpicker.view.position1); 19547 19548 that.setOptionStatus(); 19549 19550 // if searching, check to make sure the list has actually been updated before updating DOM 19551 // this prevents unnecessary repaints 19552 if (isSearching || (isVirtual === false && init)) menuIsDifferent = !isEqual(previousElements, that.selectpicker.view.visibleElements); 19553 19554 // if virtual scroll is disabled and not searching, 19555 // menu should never need to be updated more than once 19556 if ((init || isVirtual === true) && menuIsDifferent) { 19557 var menuInner = that.$menuInner[0], 19558 menuFragment = document.createDocumentFragment(), 19559 emptyMenu = menuInner.firstChild.cloneNode(false), 19560 marginTop, 19561 marginBottom, 19562 elements = isVirtual === true ? that.selectpicker.view.visibleElements : that.selectpicker.current.elements; 19563 19564 // replace the existing UL with an empty one - this is faster than $.empty() 19565 menuInner.replaceChild(emptyMenu, menuInner.firstChild); 19566 19567 for (var i = 0, visibleElementsLen = elements.length; i < visibleElementsLen; i++) { 19568 menuFragment.appendChild(elements[i]); 19569 } 19570 19571 if (isVirtual === true) { 19572 marginTop = (that.selectpicker.view.position0 === 0 ? 0 : that.selectpicker.current.data[that.selectpicker.view.position0 - 1].position); 19573 marginBottom = (that.selectpicker.view.position1 > size - 1 ? 0 : that.selectpicker.current.data[size - 1].position - that.selectpicker.current.data[that.selectpicker.view.position1 - 1].position); 19574 19575 menuInner.firstChild.style.marginTop = marginTop + 'px'; 19576 menuInner.firstChild.style.marginBottom = marginBottom + 'px'; 19577 } 19578 19579 menuInner.firstChild.appendChild(menuFragment); 19580 } 19581 } 19582 19583 that.prevActiveIndex = that.activeIndex; 19584 19585 if (!that.options.liveSearch) { 19586 that.$menuInner.focus(); 19587 } else if (isSearching && init) { 19588 var index = 0, 19589 newActive; 19590 19591 if (!that.selectpicker.view.canHighlight[index]) { 19592 index = 1 + that.selectpicker.view.canHighlight.slice(1).indexOf(true); 19593 } 19594 19595 newActive = that.selectpicker.view.visibleElements[index]; 19596 19597 if (that.selectpicker.view.currentActive) { 19598 that.selectpicker.view.currentActive.classList.remove('active'); 19599 if (that.selectpicker.view.currentActive.firstChild) that.selectpicker.view.currentActive.firstChild.classList.remove('active'); 19600 } 19601 19602 if (newActive) { 19603 newActive.classList.add('active'); 19604 if (newActive.firstChild) newActive.firstChild.classList.add('active'); 19605 } 19606 19607 that.activeIndex = that.selectpicker.current.map.originalIndex[index]; 19608 } 19609 } 19610 19611 $(window) 19612 .off('resize' + EVENT_KEY + '.' + this.selectId + '.createView') 19613 .on('resize' + EVENT_KEY + '.' + this.selectId + '.createView', function () { 19614 var isActive = that.$newElement.hasClass(classNames.SHOW); 19615 19616 if (isActive) scroll(that.$menuInner[0].scrollTop); 19617 }); 19618 }, 19619 19620 createLi: function () { 19621 var that = this, 19622 mainElements = [], 19623 hiddenOptions = {}, 19624 widestOption, 19625 availableOptionsCount = 0, 19626 widestOptionLength = 0, 19627 mainData = [], 19628 optID = 0, 19629 headerIndex = 0, 19630 liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure newIndex is correct 19631 19632 if (!this.selectpicker.view.titleOption) this.selectpicker.view.titleOption = document.createElement('option'); 19633 19634 var elementTemplates = { 19635 span: document.createElement('span'), 19636 subtext: document.createElement('small'), 19637 a: document.createElement('a'), 19638 li: document.createElement('li'), 19639 whitespace: document.createTextNode('\u00A0') 19640 }, 19641 checkMark, 19642 fragment = document.createDocumentFragment(); 19643 19644 if (that.options.showTick || that.multiple) { 19645 checkMark = elementTemplates.span.cloneNode(false); 19646 checkMark.className = that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark'; 19647 elementTemplates.a.appendChild(checkMark); 19648 } 19649 19650 elementTemplates.a.setAttribute('role', 'option'); 19651 19652 elementTemplates.subtext.className = 'text-muted'; 19653 19654 elementTemplates.text = elementTemplates.span.cloneNode(false); 19655 elementTemplates.text.className = 'text'; 19656 19657 // Helper functions 19658 /** 19659 * @param content 19660 * @param [classes] 19661 * @param [optgroup] 19662 * @returns {HTMLElement} 19663 */ 19664 var generateLI = function (content, classes, optgroup) { 19665 var li = elementTemplates.li.cloneNode(false); 19666 19667 if (content) { 19668 if (content.nodeType === 1 || content.nodeType === 11) { 19669 li.appendChild(content); 19670 } else { 19671 li.innerHTML = content; 19672 } 19673 } 19674 19675 if (typeof classes !== 'undefined' && classes !== '') li.className = classes; 19676 if (typeof optgroup !== 'undefined' && optgroup !== null) li.classList.add('optgroup-' + optgroup); 19677 19678 return li; 19679 }; 19680 19681 /** 19682 * @param text 19683 * @param [classes] 19684 * @param [inline] 19685 * @returns {string} 19686 */ 19687 var generateA = function (text, classes, inline) { 19688 var a = elementTemplates.a.cloneNode(true); 19689 19690 if (text) { 19691 if (text.nodeType === 11) { 19692 a.appendChild(text); 19693 } else { 19694 a.insertAdjacentHTML('beforeend', text); 19695 } 19696 } 19697 19698 if (typeof classes !== 'undefined' && classes !== '') a.className = classes; 19699 if (version.major === '4') a.classList.add('dropdown-item'); 19700 if (inline) a.setAttribute('style', inline); 19701 19702 return a; 19703 }; 19704 19705 var generateText = function (options) { 19706 var textElement = elementTemplates.text.cloneNode(false), 19707 optionSubtextElement, 19708 optionIconElement; 19709 19710 if (options.optionContent) { 19711 textElement.innerHTML = options.optionContent; 19712 } else { 19713 textElement.textContent = options.text; 19714 19715 if (options.optionIcon) { 19716 var whitespace = elementTemplates.whitespace.cloneNode(false); 19717 19718 optionIconElement = elementTemplates.span.cloneNode(false); 19719 optionIconElement.className = that.options.iconBase + ' ' + options.optionIcon; 19720 19721 fragment.appendChild(optionIconElement); 19722 fragment.appendChild(whitespace); 19723 } 19724 19725 if (options.optionSubtext) { 19726 optionSubtextElement = elementTemplates.subtext.cloneNode(false); 19727 optionSubtextElement.innerHTML = options.optionSubtext; 19728 textElement.appendChild(optionSubtextElement); 19729 } 19730 } 19731 19732 fragment.appendChild(textElement); 19733 19734 return fragment; 19735 }; 19736 19737 var generateLabel = function (options) { 19738 var labelTextElement = elementTemplates.text.cloneNode(false), 19739 labelSubtextElement, 19740 labelIconElement; 19741 19742 labelTextElement.innerHTML = options.labelEscaped; 19743 19744 if (options.labelIcon) { 19745 var whitespace = elementTemplates.whitespace.cloneNode(false); 19746 19747 labelIconElement = elementTemplates.span.cloneNode(false); 19748 labelIconElement.className = that.options.iconBase + ' ' + options.labelIcon; 19749 19750 fragment.appendChild(labelIconElement); 19751 fragment.appendChild(whitespace); 19752 } 19753 19754 if (options.labelSubtext) { 19755 labelSubtextElement = elementTemplates.subtext.cloneNode(false); 19756 labelSubtextElement.textContent = options.labelSubtext; 19757 labelTextElement.appendChild(labelSubtextElement); 19758 } 19759 19760 fragment.appendChild(labelTextElement); 19761 19762 return fragment; 19763 } 19764 19765 if (this.options.title && !this.multiple) { 19766 // this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased 19767 // since newIndex is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended 19768 liIndex--; 19769 19770 var element = this.$element[0], 19771 isSelected = false, 19772 titleNotAppended = !this.selectpicker.view.titleOption.parentNode; 19773 19774 if (titleNotAppended) {
19775 // Use native JS to prepend option (faster) 19776 this.selectpicker.view.titleOption.className = 'bs-title-option'; 19777 this.selectpicker.view.titleOption.value = ''; 19778 19779 // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option. 19780 // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs, 19781 // if so, the select will have the data-selected attribute 19782 var $opt = $(element.options[element.selectedIndex]); 19783 isSelected = $opt.attr('selected') === undefined && this.$element.data('selected') === undefined; 19784 } 19785 19786 if (titleNotAppended || this.selectpicker.view.titleOption.index !== 0) { 19787 element.insertBefore(this.selectpicker.view.titleOption, element.firstChild); 19788 } 19789 19790 // Set selected *after* appending to select, 19791 // otherwise the option doesn't get selected in IE 19792 // set using selectedIndex, as setting the selected attr to true here doesn't work in IE11 19793 if (isSelected) element.selectedIndex = 0; 19794 } 19795 19796 var $selectOptions = this.$element.find('option'); 19797 19798 $selectOptions.each(function (index) { 19799 var $this = $(this); 19800 19801 liIndex++; 19802 19803 if ($this.hasClass('bs-title-option')) return; 19804 19805 var thisData = $this.data(); 19806 19807 // Get the class and text for the option 19808 var optionClass = this.className || '', 19809 inline = htmlEscape(this.style.cssText), 19810 optionContent = thisData.content, 19811 text = this.textContent, 19812 tokens = thisData.tokens, 19813 subtext = thisData.subtext, 19814 icon = thisData.icon, 19815 $parent = $this.parent(), 19816 parent = $parent[0], 19817 isOptgroup = parent.tagName === 'OPTGROUP', 19818 isOptgroupDisabled = isOptgroup && parent.disabled, 19819 isDisabled = this.disabled || isOptgroupDisabled, 19820 prevHiddenIndex, 19821 showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP', 19822 textElement, 19823 labelElement, 19824 prevHidden; 19825 19826 var parentData = $parent.data(); 19827 19828 if ((thisData.hidden === true || this.hidden) || (that.options.hideDisabled && (isDisabled || isOptgroupDisabled))) { 19829 // set prevHiddenIndex - the index of the first hidden option in a group of hidden options 19830 // used to determine whether or not a divider should be placed after an optgroup if there are 19831 // hidden options between the optgroup and the first visible option 19832 prevHiddenIndex = thisData.prevHiddenIndex; 19833 $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index)); 19834 19835 liIndex--; 19836 19837 hiddenOptions[index] = { 19838 type: 'hidden', 19839 data: thisData 19840 } 19841 19842 // if previous element is not an optgroup 19843 if (!showDivider) { 19844 if (prevHiddenIndex !== undefined) { 19845 // select the element **before** the first hidden element in the group 19846 prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling; 19847 19848 if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) { 19849 showDivider = true; 19850 } 19851 } 19852 } 19853 19854 if (showDivider && mainData[mainData.length - 1].type !== 'divider') { 19855 liIndex++; 19856 mainElements.push( 19857 generateLI( 19858 false, 19859 classNames.DIVIDER, 19860 optID + 'div' 19861 ) 19862 ); 19863 mainData.push({ 19864 type: 'divider', 19865 optID: optID 19866 }); 19867 } 19868 19869 return; 19870 } 19871 19872 if (isOptgroup && thisData.divider !== true) { 19873 if (that.options.hideDisabled && isDisabled) { 19874 if (parentData.allOptionsDisabled === undefined) { 19875 var $options = $parent.children(); 19876 $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length); 19877 } 19878 19879 if ($parent.data('allOptionsDisabled')) { 19880 liIndex--; 19881 return; 19882 } 19883 } 19884 19885 var optGroupClass = ' ' + parent.className || '', 19886 previousOption = this.previousElementSibling; 19887 19888 prevHiddenIndex = thisData.prevHiddenIndex; 19889 19890 if (prevHiddenIndex !== undefined) { 19891 previousOption = $selectOptions[prevHiddenIndex].previousElementSibling; 19892 } 19893 19894 if (!previousOption) { // Is it the first option of the optgroup? 19895 optID += 1; 19896 19897 // Get the opt group label 19898 var label = parent.label, 19899 labelEscaped = htmlEscape(label), 19900 labelSubtext = parentData.subtext, 19901 labelIcon = parentData.icon; 19902 19903 if (index !== 0 && mainElements.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown? 19904 liIndex++; 19905 mainElements.push( 19906 generateLI( 19907 false, 19908 classNames.DIVIDER, 19909 optID + 'div' 19910 ) 19911 ); 19912 mainData.push({ 19913 type: 'divider', 19914 optID: optID 19915 }); 19916 } 19917 liIndex++; 19918 19919 labelElement = generateLabel({ 19920 labelEscaped: labelEscaped, 19921 labelSubtext: labelSubtext, 19922 labelIcon: labelIcon 19923 }); 19924 19925 mainElements.push(generateLI(labelElement, 'dropdown-header' + optGroupClass, optID)); 19926 mainData.push({ 19927 content: labelEscaped, 19928 subtext: labelSubtext, 19929 type: 'optgroup-label', 19930 optID: optID 19931 }); 19932 19933 headerIndex = liIndex - 1; 19934 } 19935 19936 textElement = generateText({ 19937 text: text, 19938 optionContent: optionContent, 19939 optionSubtext: subtext, 19940 optionIcon: icon 19941 }); 19942 19943 mainElements.push(generateLI(generateA(textElement, 'opt ' + optionClass + optGroupClass, inline), '', optID)); 19944 mainData.push({ 19945 content: optionContent || text, 19946 subtext: subtext, 19947 tokens: tokens, 19948 type: 'option', 19949 optID: optID, 19950 headerIndex: headerIndex, 19951 lastIndex: headerIndex + parent.childElementCount, 19952 originalIndex: index, 19953 data: thisData 19954 }); 19955 19956 availableOptionsCount++; 19957 } else if (thisData.divider === true) { 19958 mainElements.push(generateLI(false, classNames.DIVIDER)); 19959 mainData.push({ 19960 type: 'divider', 19961 originalIndex: index, 19962 data: thisData 19963 }); 19964 } else { 19965 // if previous element is not an optgroup and hideDisabled is true 19966 if (!showDivider && that.options.hideDisabled) { 19967 prevHiddenIndex = thisData.prevHiddenIndex; 19968 19969 if (prevHiddenIndex !== undefined) { 19970 // select the element **before** the first hidden element in the group 19971 prevHidden = $selectOptions[prevHiddenIndex].previousElementSibling; 19972 19973 if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) { 19974 showDivider = true; 19975 } 19976 } 19977 } 19978
19979 if (showDivider && mainData[mainData.length - 1].type !== 'divider') { 19980 liIndex++; 19981 mainElements.push( 19982 generateLI( 19983 false, 19984 classNames.DIVIDER, 19985 optID + 'div' 19986 ) 19987 ); 19988 mainData.push({ 19989 type: 'divider', 19990 optID: optID 19991 }); 19992 } 19993 19994 textElement = generateText({ 19995 text: text, 19996 optionContent: optionContent, 19997 optionSubtext: subtext, 19998 optionIcon: icon 19999 }); 20000 20001 mainElements.push(generateLI(generateA(textElement, optionClass, inline))); 20002 mainData.push({ 20003 content: optionContent || text, 20004 subtext: subtext, 20005 tokens: tokens, 20006 type: 'option', 20007 originalIndex: index, 20008 data: thisData 20009 }); 20010 20011 availableOptionsCount++; 20012 } 20013 20014 that.selectpicker.main.map.newIndex[index] = liIndex; 20015 that.selectpicker.main.map.originalIndex[liIndex] = index; 20016 20017 // get the most recent option info added to mainData 20018 var _mainDataLast = mainData[mainData.length - 1]; 20019 20020 _mainDataLast.disabled = isDisabled; 20021 20022 var combinedLength = 0; 20023 20024 // count the number of characters in the option - not perfect, but should work in most cases 20025 if (_mainDataLast.content) combinedLength += _mainDataLast.content.length; 20026 if (_mainDataLast.subtext) combinedLength += _mainDataLast.subtext.length; 20027 // if there is an icon, ensure this option's width is checked
20028 if (icon) combinedLength += 1; 20029 20030 if (combinedLength > widestOptionLength) { 20031 widestOptionLength = combinedLength; 20032 20033 // guess which option is the widest 20034 // use this when calculating menu width 20035 // not perfect, but it's fast, and the width will be updating accordingly when scrolling 20036 widestOption = mainElements[mainElements.length - 1]; 20037 } 20038 }); 20039 20040 this.selectpicker.main.elements = mainElements; 20041 this.selectpicker.main.data = mainData; 20042 this.selectpicker.main.hidden = hiddenOptions; 20043 20044 this.selectpicker.current = this.selectpicker.main; 20045 20046 this.selectpicker.view.widestOption = widestOption; 20047 this.selectpicker.view.availableOptionsCount = availableOptionsCount; // faster way to get # of available options without filter 20048 }, 20049 20050 findLis: function () { 20051 return this.$menuInner.find('.inner > li'); 20052 }, 20053 20054 render: function () { 20055 var that = this, 20056 $selectOptions = this.$element.find('option'), 20057 selectedItems = [], 20058 selectedItemsInTitle = []; 20059 20060 this.togglePlaceholder(); 20061 20062 this.tabIndex(); 20063 20064 for (var index = 0, len = $selectOptions.length; index < len; index++) { 20065 var i = that.selectpicker.main.map.newIndex[index], 20066 option = $selectOptions[index], 20067 optionData = that.selectpicker.main.data[i] || that.selectpicker.main.hidden[index]; 20068 20069 if (option && option.selected && optionData) { 20070 selectedItems.push(option); 20071 20072 if ((selectedItemsInTitle.length < 100 && that.options.selectedTextFormat !== 'count') || selectedItems.length === 1) { 20073 var thisData = optionData.data, 20074 icon = thisData.icon && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + thisData.icon + '"></i> ' : '', 20075 subtext, 20076 titleItem; 20077 20078 if (that.options.showSubtext && thisData.subtext && !that.multiple) { 20079 subtext = ' <small class="text-muted">' + thisData.subtext + '</small>'; 20080 } else { 20081 subtext = ''; 20082 } 20083 20084 if (option.title) { 20085 titleItem = option.title; 20086 } else if (thisData.content && that.options.showContent) { 20087 titleItem = thisData.content.toString(); 20088 } else { 20089 titleItem = icon + option.innerHTML.trim() + subtext; 20090 } 20091 20092 selectedItemsInTitle.push(titleItem); 20093 } 20094 } 20095 } 20096 20097 // Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled 20098 // Convert all the values into a comma delimited string 20099 var title = !this.multiple ? selectedItemsInTitle[0] : selectedItemsInTitle.join(this.options.multipleSeparator); 20100 20101 // add ellipsis 20102 if (selectedItems.length > 50) title += '...'; 20103 20104 // If this is a multiselect, and selectedTextFormat is count, then show 1 of 2 selected etc.. 20105 if (this.multiple && this.options.selectedTextFormat.indexOf('count') !== -1) { 20106 var max = this.options.selectedTextFormat.split('>'); 20107 20108 if ((max.length > 1 && selectedItems.length > max[1]) || (max.length === 1 && selectedItems.length >= 2)) { 20109 var totalCount = this.selectpicker.view.availableOptionsCount, 20110 tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText; 20111 20112 title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString()); 20113 } 20114 } 20115 20116 if (this.options.title == undefined) { 20117 // use .attr to ensure undefined is returned if title attribute is not set 20118 this.options.title = this.$element.attr('title'); 20119 } 20120 20121 if (this.options.selectedTextFormat == 'static') { 20122 title = this.options.title; 20123 } 20124 20125 // If the select doesn't have a title, then use the default, or if nothing is set at all, use noneSelectedText 20126 if (!title) { 20127 title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText; 20128 } 20129 20130 // strip all HTML tags and trim the result, then unescape any escaped tags 20131 this.$button[0].title = htmlUnescape(title.replace(/<[^>]*>?/g, '').trim()); 20132 this.$button.find('.filter-option-inner-inner')[0].innerHTML = title; 20133 20134 this.$element.trigger('rendered' + EVENT_KEY); 20135 }, 20136 20137 /** 20138 * @param [style] 20139 * @param [status] 20140 */ 20141 setStyle: function (style, status) { 20142 if (this.$element.attr('class')) { 20143 this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, '')); 20144 } 20145 20146 var buttonClass = style || this.options.style; 20147 20148 if (status == 'add') { 20149 this.$button.addClass(buttonClass); 20150 } else if (status == 'remove') { 20151 this.$button.removeClass(buttonClass); 20152 } else { 20153 this.$button.removeClass(this.options.style); 20154 this.$button.addClass(buttonClass); 20155 } 20156 }, 20157 20158 liHeight: function (refresh) { 20159 if (!refresh && (this.options.size === false || this.sizeInfo)) return; 20160 20161 if (!this.sizeInfo) this.sizeInfo = {}; 20162 20163 var newElement = document.createElement('div'), 20164 menu = document.createElement('div'), 20165 menuInner = document.createElement('div'), 20166 menuInnerInner = document.createElement('ul'), 20167 divider = document.createElement('li'), 20168 dropdownHeader = document.createElement('li'), 20169 li = document.createElement('li'), 20170 a = document.createElement('a'), 20171 text = document.createElement('span'), 20172 header = this.options.header && this.$menu.find('.' + classNames.POPOVERHEADER).length > 0 ? this.$menu.find('.' + classNames.POPOVERHEADER)[0].cloneNode(true) : null, 20173 search = this.options.liveSearch ? document.createElement('div') : null, 20174 actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null, 20175 doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null, 20176 firstOption = this.$element.find('option')[0]; 20177 20178 this.sizeInfo.selectWidth = this.$newElement[0].offsetWidth; 20179 20180 text.className = 'text'; 20181 a.className = 'dropdown-item ' + (firstOption ? firstOption.className : ''); 20182 newElement.className = this.$menu[0].parentNode.className + ' ' + classNames.SHOW; 20183 newElement.style.width = this.sizeInfo.selectWidth + 'px'; 20184 if (this.options.width === 'auto') menu.style.minWidth = 0; 20185 menu.className = classNames.MENU + ' ' + classNames.SHOW; 20186 menuInner.className = 'inner ' + classNames.SHOW; 20187 menuInnerInner.className = classNames.MENU + ' inner ' + (version.major === '4' ? classNames.SHOW : ''); 20188 divider.className = classNames.DIVIDER; 20189 dropdownHeader.className = 'dropdown-header'; 20190 20191 text.appendChild(document.createTextNode('\u200b')); 20192 a.appendChild(text); 20193 li.appendChild(a); 20194 dropdownHeader.appendChild(text.cloneNode(true)); 20195 20196 if (this.selectpicker.view.widestOption) { 20197 menuInnerInner.appendChild(this.selectpicker.view.widestOption.cloneNode(true)); 20198 } 20199 20200 menuInnerInner.appendChild(li); 20201 menuInnerInner.appendChild(divider); 20202 menuInnerInner.appendChild(dropdownHeader); 20203 if (header) menu.appendChild(header); 20204 if (search) { 20205 var input = document.createElement('input'); 20206 search.className = 'bs-searchbox'; 20207 input.className = 'form-control'; 20208 search.appendChild(input); 20209 menu.appendChild(search); 20210 } 20211 if (actions) menu.appendChild(actions); 20212 menuInner.appendChild(menuInnerInner); 20213 menu.appendChild(menuInner); 20214 if (doneButton) menu.appendChild(doneButton); 20215 newElement.appendChild(menu); 20216 20217 document.body.appendChild(newElement); 20218 20219 var liHeight = a.offsetHeight, 20220 dropdownHeaderHeight = dropdownHeader ? dropdownHeader.offsetHeight : 0, 20221 headerHeight = header ? header.offsetHeight : 0, 20222 searchHeight = search ? search.offsetHeight : 0, 20223 actionsHeight = actions ? actions.offsetHeight : 0, 20224 doneButtonHeight = doneButton ? doneButton.offsetHeight : 0, 20225 dividerHeight = $(divider).outerHeight(true), 20226 // fall back to jQuery if getComputedStyle is not supported 20227 menuStyle = window.getComputedStyle ? window.getComputedStyle(menu) : false, 20228 menuWidth = menu.offsetWidth, 20229 $menu = menuStyle ? null : $(menu), 20230 menuPadding = { 20231 vert: toInteger(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) + 20232 toInteger(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) + 20233 toInteger(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) + 20234 toInteger(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')), 20235 horiz: toInteger(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) + 20236 toInteger(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) + 20237 toInteger(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) + 20238 toInteger(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth')) 20239 }, 20240 menuExtras = { 20241 vert: menuPadding.vert + 20242 toInteger(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) + 20243 toInteger(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2, 20244 horiz: menuPadding.horiz + 20245 toInteger(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) + 20246 toInteger(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2 20247 }, 20248 scrollBarWidth; 20249 20250 menuInner.style.overflowY = 'scroll'; 20251 20252 scrollBarWidth = menu.offsetWidth - menuWidth; 20253 20254 document.body.removeChild(newElement); 20255 20256 this.sizeInfo.liHeight = liHeight; 20257 this.sizeInfo.dropdownHeaderHeight = dropdownHeaderHeight; 20258 this.sizeInfo.headerHeight = headerHeight; 20259 this.sizeInfo.searchHeight = searchHeight; 20260 this.sizeInfo.actionsHeight = actionsHeight; 20261 this.sizeInfo.doneButtonHeight = doneButtonHeight;
vendor: 12,975 bytes, lines 20262-20572
20262 this.sizeInfo.dividerHeight = dividerHeight; 20263 this.sizeInfo.menuPadding = menuPadding; 20264 this.sizeInfo.menuExtras = menuExtras; 20265 this.sizeInfo.menuWidth = menuWidth; 20266 this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth; 20267 this.sizeInfo.scrollBarWidth = scrollBarWidth; 20268 this.sizeInfo.selectHeight = this.$newElement[0].offsetHeight; 20269 20270 this.setPositionData(); 20271 }, 20272 20273 getSelectPosition: function () { 20274 var that = this, 20275 $window = $(window), 20276 pos = that.$newElement.offset(), 20277 $container = $(that.options.container), 20278 containerPos; 20279 20280 if (that.options.container && !$container.is('body')) { 20281 containerPos = $container.offset(); 20282 containerPos.top += parseInt($container.css('borderTopWidth')); 20283 containerPos.left += parseInt($container.css('borderLeftWidth')); 20284 } else { 20285 containerPos = { top: 0, left: 0 }; 20286 } 20287 20288 var winPad = that.options.windowPadding; 20289 20290 this.sizeInfo.selectOffsetTop = pos.top - containerPos.top - $window.scrollTop(); 20291 this.sizeInfo.selectOffsetBot = $window.height() - this.sizeInfo.selectOffsetTop - this.sizeInfo.selectHeight - containerPos.top - winPad[2]; 20292 this.sizeInfo.selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft(); 20293 this.sizeInfo.selectOffsetRight = $window.width() - this.sizeInfo.selectOffsetLeft - this.sizeInfo.selectWidth - containerPos.left - winPad[1]; 20294 this.sizeInfo.selectOffsetTop -= winPad[0]; 20295 this.sizeInfo.selectOffsetLeft -= winPad[3]; 20296 }, 20297 20298 setMenuSize: function (isAuto) { 20299 this.getSelectPosition(); 20300 20301 var selectWidth = this.sizeInfo.selectWidth, 20302 liHeight = this.sizeInfo.liHeight, 20303 headerHeight = this.sizeInfo.headerHeight, 20304 searchHeight = this.sizeInfo.searchHeight, 20305 actionsHeight = this.sizeInfo.actionsHeight, 20306 doneButtonHeight = this.sizeInfo.doneButtonHeight, 20307 divHeight = this.sizeInfo.dividerHeight, 20308 menuPadding = this.sizeInfo.menuPadding, 20309 menuInnerHeight, 20310 menuHeight, 20311 divLength = 0, 20312 minHeight, 20313 _minHeight, 20314 maxHeight, 20315 menuInnerMinHeight, 20316 estimate; 20317 20318 if (this.options.dropupAuto) { 20319 // Get the estimated height of the menu without scrollbars. 20320 // This is useful for smaller menus, where there might be plenty of room 20321 // below the button without setting dropup, but we can't know 20322 // the exact height of the menu until createView is called later 20323 estimate = liHeight * this.selectpicker.current.elements.length + menuPadding.vert; 20324 this.$newElement.toggleClass(classNames.DROPUP, this.sizeInfo.selectOffsetTop - this.sizeInfo.selectOffsetBot > this.sizeInfo.menuExtras.vert && estimate + this.sizeInfo.menuExtras.vert + 50 > this.sizeInfo.selectOffsetBot); 20325 } 20326 20327 if (this.options.size === 'auto') { 20328 _minHeight = this.selectpicker.current.elements.length > 3 ? this.sizeInfo.liHeight * 3 + this.sizeInfo.menuExtras.vert - 2 : 0; 20329 menuHeight = this.sizeInfo.selectOffsetBot - this.sizeInfo.menuExtras.vert; 20330 minHeight = _minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight; 20331 menuInnerMinHeight = Math.max(_minHeight - menuPadding.vert, 0); 20332 20333 if (this.$newElement.hasClass(classNames.DROPUP)) { 20334 menuHeight = this.sizeInfo.selectOffsetTop - this.sizeInfo.menuExtras.vert; 20335 } 20336 20337 maxHeight = menuHeight; 20338 menuInnerHeight = menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert; 20339 } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) { 20340 for (var i = 0; i < this.options.size; i++) { 20341 if (this.selectpicker.current.data[i].type === 'divider') divLength++; 20342 } 20343 20344 menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert; 20345 menuInnerHeight = menuHeight - menuPadding.vert; 20346 maxHeight = menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight; 20347 minHeight = menuInnerMinHeight = ''; 20348 } 20349 20350 if (this.options.dropdownAlignRight === 'auto') { 20351 this.$menu.toggleClass(classNames.MENURIGHT, this.sizeInfo.selectOffsetLeft > this.sizeInfo.selectOffsetRight && this.sizeInfo.selectOffsetRight < (this.sizeInfo.totalMenuWidth - selectWidth)); 20352 } 20353 20354 this.$menu.css({ 20355 'max-height': maxHeight + 'px', 20356 'overflow': 'hidden', 20357 'min-height': minHeight + 'px' 20358 }); 20359 20360 this.$menuInner.css({ 20361 'max-height': menuInnerHeight + 'px', 20362 'overflow-y': 'auto', 20363 'min-height': menuInnerMinHeight + 'px' 20364 }); 20365 20366 this.sizeInfo.menuInnerHeight = menuInnerHeight; 20367 20368 if (this.selectpicker.current.data.length && this.selectpicker.current.data[this.selectpicker.current.data.length - 1].position > this.sizeInfo.menuInnerHeight) { 20369 this.sizeInfo.hasScrollBar = true; 20370 this.sizeInfo.totalMenuWidth = this.sizeInfo.menuWidth + this.sizeInfo.scrollBarWidth; 20371 20372 this.$menu.css('min-width', this.sizeInfo.totalMenuWidth); 20373 } 20374 20375 if (this.dropdown && this.dropdown._popper) this.dropdown._popper.update(); 20376 }, 20377 20378 setSize: function (refresh) { 20379 this.liHeight(refresh); 20380 20381 if (this.options.header) this.$menu.css('padding-top', 0); 20382 if (this.options.size === false) return; 20383 20384 var that = this, 20385 $window = $(window), 20386 selectedIndex, 20387 offset = 0; 20388 20389 this.setMenuSize(); 20390 20391 if (this.options.size === 'auto') { 20392 this.$searchbox 20393 .off('input.setMenuSize propertychange.setMenuSize') 20394 .on('input.setMenuSize propertychange.setMenuSize', function () { 20395 return that.setMenuSize(); 20396 }); 20397 20398 $window 20399 .off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize') 20400 .on('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize', function () { 20401 return that.setMenuSize(); 20402 }); 20403 } else if (this.options.size && this.options.size != 'auto' && this.selectpicker.current.elements.length > this.options.size) { 20404 this.$searchbox.off('input.setMenuSize propertychange.setMenuSize'); 20405 $window.off('resize' + EVENT_KEY + '.' + this.selectId + '.setMenuSize' + ' scroll' + EVENT_KEY + '.' + this.selectId + '.setMenuSize'); 20406 } 20407 20408 if (refresh) { 20409 offset = this.$menuInner[0].scrollTop; 20410 } else if (!that.multiple) { 20411 selectedIndex = that.selectpicker.main.map.newIndex[that.$element[0].selectedIndex]; 20412 20413 if (typeof selectedIndex === 'number' && that.options.size !== false) { 20414 offset = that.sizeInfo.liHeight * selectedIndex; 20415 offset = offset - (that.sizeInfo.menuInnerHeight / 2) + (that.sizeInfo.liHeight / 2); 20416 } 20417 } 20418 20419 that.createView(false, offset); 20420 }, 20421 20422 setWidth: function () { 20423 var that = this; 20424 20425 if (this.options.width === 'auto') { 20426 requestAnimationFrame(function () { 20427 that.$menu.css('min-width', '0'); 20428 that.liHeight(); 20429 that.setMenuSize(); 20430 20431 // Get correct width if element is hidden 20432 var $selectClone = that.$newElement.clone().appendTo('body'), 20433 btnWidth = $selectClone.css('width', 'auto').children('button').outerWidth(); 20434 20435 $selectClone.remove(); 20436 20437 // Set width to whatever's larger, button title or longest option 20438 that.sizeInfo.selectWidth = Math.max(that.sizeInfo.totalMenuWidth, btnWidth); 20439 that.$newElement.css('width', that.sizeInfo.selectWidth + 'px'); 20440 }); 20441 } else if (this.options.width === 'fit') { 20442 // Remove inline min-width so width can be changed from 'auto' 20443 this.$menu.css('min-width', ''); 20444 this.$newElement.css('width', '').addClass('fit-width'); 20445 } else if (this.options.width) { 20446 // Remove inline min-width so width can be changed from 'auto' 20447 this.$menu.css('min-width', ''); 20448 this.$newElement.css('width', this.options.width); 20449 } else { 20450 // Remove inline min-width/width so width can be changed 20451 this.$menu.css('min-width', ''); 20452 this.$newElement.css('width', ''); 20453 } 20454 // Remove fit-width class if width is changed programmatically 20455 if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') { 20456 this.$newElement.removeClass('fit-width'); 20457 } 20458 }, 20459 20460 selectPosition: function () { 20461 this.$bsContainer = $('<div class="bs-container" />'); 20462 20463 var that = this, 20464 $container = $(this.options.container), 20465 pos, 20466 containerPos, 20467 actualHeight, 20468 getPlacement = function ($element) { 20469 var containerPosition = {}, 20470 // fall back to dropdown's default display setting if display is not manually set 20471 display = that.options.display || ( 20472 // Bootstrap 3 doesn't have $.fn.dropdown.Constructor.Default 20473 $.fn.dropdown.Constructor.Default ? $.fn.dropdown.Constructor.Default.display 20474 : false 20475 ); 20476 20477 that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass(classNames.DROPUP, $element.hasClass(classNames.DROPUP)); 20478 pos = $element.offset(); 20479 20480 if (!$container.is('body')) { 20481 containerPos = $container.offset(); 20482 containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop(); 20483 containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft(); 20484 } else { 20485 containerPos = { top: 0, left: 0 }; 20486 } 20487 20488 actualHeight = $element.hasClass(classNames.DROPUP) ? 0 : $element[0].offsetHeight; 20489 20490 // Bootstrap 4+ uses Popper for menu positioning 20491 if (version.major < 4 || display === 'static') { 20492 containerPosition.top = pos.top - containerPos.top + actualHeight; 20493 containerPosition.left = pos.left - containerPos.left; 20494 } 20495 20496 containerPosition.width = $element[0].offsetWidth; 20497 20498 that.$bsContainer.css(containerPosition); 20499 }; 20500 20501 this.$button.on('click.bs.dropdown.data-api', function () { 20502 if (that.isDisabled()) { 20503 return; 20504 } 20505 20506 getPlacement(that.$newElement); 20507 20508 that.$bsContainer 20509 .appendTo(that.options.container) 20510 .toggleClass(classNames.SHOW, !that.$button.hasClass(classNames.SHOW)) 20511 .append(that.$menu); 20512 }); 20513 20514 $(window) 20515 .off('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId) 20516 .on('resize' + EVENT_KEY + '.' + this.selectId + ' scroll' + EVENT_KEY + '.' + this.selectId, function () { 20517 var isActive = that.$newElement.hasClass(classNames.SHOW); 20518 20519 if (isActive) getPlacement(that.$newElement); 20520 }); 20521 20522 this.$element.on('hide' + EVENT_KEY, function () { 20523 that.$menu.data('height', that.$menu.height()); 20524 that.$bsContainer.detach(); 20525 }); 20526 }, 20527 20528 setOptionStatus: function () { 20529 var that = this, 20530 $selectOptions = this.$element.find('option'); 20531 20532 that.noScroll = false; 20533 20534 if (that.selectpicker.view.visibleElements && that.selectpicker.view.visibleElements.length) { 20535 for (var i = 0; i < that.selectpicker.view.visibleElements.length; i++) { 20536 var index = that.selectpicker.current.map.originalIndex[i + that.selectpicker.view.position0], // faster than $(li).data('originalIndex') 20537 option = $selectOptions[index]; 20538 20539 if (option) { 20540 var liIndex = this.selectpicker.main.map.newIndex[index], 20541 li = this.selectpicker.main.elements[liIndex]; 20542 20543 that.setDisabled( 20544 index, 20545 option.disabled || (option.parentNode.tagName === 'OPTGROUP' && option.parentNode.disabled), 20546 liIndex, 20547 li 20548 ); 20549 20550 that.setSelected( 20551 index, 20552 option.selected, 20553 liIndex, 20554 li 20555 ); 20556 } 20557 } 20558 } 20559 }, 20560 20561 /** 20562 * @param {number} index - the index of the option that is being changed 20563 * @param {boolean} selected - true if the option is being selected, false if being deselected 20564 */ 20565 setSelected: function (index, selected, liIndex, li) { 20566 var activeIndexIsSet = this.activeIndex !== undefined, 20567 thisIsActive = this.activeIndex === index, 20568 prevActiveIndex, 20569 prevActive, 20570 a, 20571 // if current option is already active 20572 // OR
20573 // if the current option is being selected, it's NOT multiple, and 20574 // activeIndex is undefined: 20575 // - when the menu is first being opened, OR 20576 // - after a search has been performed, OR 20577 // - when retainActive is false when selecting a new option (i.e. index of the newly selected option is not the same as the current activeIndex) 20578 keepActive = thisIsActive || (selected && !this.multiple && !activeIndexIsSet); 20579 20580 if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index]; 20581 if (!li) li = this.selectpicker.main.elements[liIndex]; 20582 20583 a = li.firstChild; 20584 20585 if (selected) { 20586 this.selectedIndex = index; 20587 } 20588 20589 li.classList.toggle('selected', selected); 20590 li.classList.toggle('active', keepActive); 20591 20592 if (keepActive) { 20593 this.selectpicker.view.currentActive = li; 20594 this.activeIndex = index; 20595 } 20596 20597 if (a) { 20598 a.classList.toggle('selected', selected); 20599 a.classList.toggle('active', keepActive); 20600 a.setAttribute('aria-selected', selected); 20601 } 20602 20603 if (!keepActive) { 20604 if (!activeIndexIsSet && selected && this.prevActiveIndex !== undefined) { 20605 prevActiveIndex = this.selectpicker.main.map.newIndex[this.prevActiveIndex]; 20606 prevActive = this.selectpicker.main.elements[prevActiveIndex]; 20607 20608 prevActive.classList.remove('active'); 20609 if (prevActive.firstChild) { 20610 prevActive.firstChild.classList.remove('active'); 20611 } 20612 } 20613 } 20614 }, 20615 20616 /** 20617 * @param {number} index - the index of the option that is being disabled 20618 * @param {boolean} disabled - true if the option is being disabled, false if being enabled 20619 */ 20620 setDisabled: function (index, disabled, liIndex, li) { 20621 var a; 20622 20623 if (!liIndex) liIndex = this.selectpicker.main.map.newIndex[index]; 20624 if (!li) li = this.selectpicker.main.elements[liIndex]; 20625 20626 a = li.firstChild; 20627 20628 li.classList.toggle(classNames.DISABLED, disabled); 20629 20630 if (a) { 20631 if (version.major === '4') a.classList.toggle(classNames.DISABLED, disabled); 20632 20633 a.setAttribute('aria-disabled', disabled); 20634 20635 if (disabled) { 20636 a.setAttribute('tabindex', -1); 20637 } else { 20638 a.setAttribute('tabindex', 0); 20639 } 20640 } 20641 }, 20642 20643 isDisabled: function () { 20644 return this.$element[0].disabled; 20645 }, 20646 20647 checkDisabled: function () { 20648 var that = this; 20649 20650 if (this.isDisabled()) { 20651 this.$newElement.addClass(classNames.DISABLED); 20652 this.$button.addClass(classNames.DISABLED).attr('tabindex', -1).attr('aria-disabled', true); 20653 } else { 20654 if (this.$button.hasClass(classNames.DISABLED)) { 20655 this.$newElement.removeClass(classNames.DISABLED); 20656 this.$button.removeClass(classNames.DISABLED).attr('aria-disabled', false); 20657 } 20658 20659 if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) { 20660 this.$button.removeAttr('tabindex'); 20661 } 20662 } 20663 20664 this.$button.click(function () { 20665 return !that.isDisabled(); 20666 }); 20667 }, 20668 20669 togglePlaceholder: function () { 20670 // much faster than calling $.val() 20671 var element = this.$element[0], 20672 selectedIndex = element.selectedIndex, 20673 nothingSelected = selectedIndex === -1; 20674 20675 if (!nothingSelected && !element.options[selectedIndex].value) nothingSelected = true; 20676 20677 this.$button.toggleClass('bs-placeholder', nothingSelected); 20678 }, 20679 20680 tabIndex: function () { 20681 if (this.$element.data('tabindex') !== this.$element.attr('tabindex') && 20682 (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) { 20683 this.$element.data('tabindex', this.$element.attr('tabindex')); 20684 this.$button.attr('tabindex', this.$element.data('tabindex')); 20685 } 20686 20687 this.$element.attr('tabindex', -98); 20688 }, 20689 20690 clickListener: function () { 20691 var that = this, 20692 $document = $(document); 20693 20694 $document.data('spaceSelect', false); 20695 20696 this.$button.on('keyup', function (e) { 20697 if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) { 20698 e.preventDefault(); 20699 $document.data('spaceSelect', false); 20700 } 20701 }); 20702 20703 this.$newElement.on('show.bs.dropdown', function () { 20704 if (version.major > 3 && !that.dropdown) { 20705 that.dropdown = that.$button.data('bs.dropdown'); 20706 that.dropdown._menu = that.$menu[0]; 20707 } 20708 }); 20709 20710 this.$button.on('click.bs.dropdown.data-api', function () { 20711 if (!that.$newElement.hasClass(classNames.SHOW)) { 20712 that.setSize(); 20713 } 20714 }); 20715 20716 function setFocus () { 20717 if (that.options.liveSearch) { 20718 that.$searchbox.focus(); 20719 } else { 20720 that.$menuInner.focus(); 20721 } 20722 } 20723 20724 function checkPopperExists () { 20725 if (that.dropdown && that.dropdown._popper && that.dropdown._popper.state.isCreated) { 20726 setFocus(); 20727 } else { 20728 requestAnimationFrame(checkPopperExists); 20729 } 20730 } 20731 20732 this.$element.on('shown' + EVENT_KEY, function () {
20733 if (that.$menuInner[0].scrollTop !== that.selectpicker.view.scrollTop) { 20734 that.$menuInner[0].scrollTop = that.selectpicker.view.scrollTop; 20735 } 20736 20737 if (version.major > 3) { 20738 requestAnimationFrame(checkPopperExists); 20739 } else { 20740 setFocus(); 20741 } 20742 }); 20743 20744 this.$menuInner.on('click', 'li a', function (e, retainActive) { 20745 var $this = $(this), 20746 position0 = that.isVirtual() ? that.selectpicker.view.position0 : 0, 20747 clickedIndex = that.selectpicker.current.map.originalIndex[$this.parent().index() + position0], 20748 prevValue = getSelectValues(that.$element[0]), 20749 prevIndex = that.$element.prop('selectedIndex'), 20750 triggerChange = true; 20751 20752 // Don't close on multi choice menu 20753 if (that.multiple && that.options.maxOptions !== 1) { 20754 e.stopPropagation(); 20755 } 20756 20757 e.preventDefault(); 20758 20759 // Don't run if the select is disabled 20760 if (!that.isDisabled() && !$this.parent().hasClass(classNames.DISABLED)) { 20761 var $options = that.$element.find('option'), 20762 $option = $options.eq(clickedIndex), 20763 state = $option.prop('selected'), 20764 $optgroup = $option.parent('optgroup'), 20765 $optgroupOptions = $optgroup.find('option'), 20766 maxOptions = that.options.maxOptions, 20767 maxOptionsGrp = $optgroup.data('maxOptions') || false; 20768 20769 if (clickedIndex === that.activeIndex) retainActive = true; 20770 20771 if (!retainActive) { 20772 that.prevActiveIndex = that.activeIndex; 20773 that.activeIndex = undefined; 20774 } 20775 20776 if (!that.multiple) { // Deselect all others if not multi select box 20777 $options.prop('selected', false); 20778 $option.prop('selected', true); 20779 that.setSelected(clickedIndex, true); 20780 } else { // Toggle the one we have chosen if we are multi select. 20781 $option.prop('selected', !state); 20782 20783 that.setSelected(clickedIndex, !state); 20784 $this.blur(); 20785 20786 if (maxOptions !== false || maxOptionsGrp !== false) { 20787 var maxReached = maxOptions < $options.filter(':selected').length, 20788 maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length; 20789 20790 if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) { 20791 if (maxOptions && maxOptions == 1) { 20792 $options.prop('selected', false); 20793 $option.prop('selected', true); 20794 20795 for (var i = 0; i < $options.length; i++) { 20796 that.setSelected(i, false); 20797 } 20798 20799 that.setSelected(clickedIndex, true); 20800 } else if (maxOptionsGrp && maxOptionsGrp == 1) { 20801 $optgroup.find('option:selected').prop('selected', false); 20802 $option.prop('selected', true); 20803 20804 for (var i = 0; i < $optgroupOptions.length; i++) { 20805 var option = $optgroupOptions[i]; 20806 that.setSelected($options.index(option), false); 20807 } 20808 20809 that.setSelected(clickedIndex, true); 20810 } else { 20811 var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText, 20812 maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText, 20813 maxTxt = maxOptionsArr[0].replace('{n}', maxOptions), 20814 maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp), 20815 $notify = $('<div class="notify"></div>'); 20816 // If {var} is set in array, replace it 20817 /** @deprecated */ 20818 if (maxOptionsArr[2]) { 20819 maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]); 20820 maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]); 20821 } 20822 20823 $option.prop('selected', false); 20824 20825 that.$menu.append($notify); 20826 20827 if (maxOptions && maxReached) { 20828 $notify.append($('<div>' + maxTxt + '</div>')); 20829 triggerChange = false;
20830 that.$element.trigger('maxReached' + EVENT_KEY); 20831 } 20832 20833 if (maxOptionsGrp && maxReachedGrp) { 20834 $notify.append($('<div>' + maxTxtGrp + '</div>')); 20835 triggerChange = false; 20836 that.$element.trigger('maxReachedGrp' + EVENT_KEY); 20837 } 20838 20839 setTimeout(function () { 20840 that.setSelected(clickedIndex, false); 20841 }, 10); 20842 20843 $notify.delay(750).fadeOut(300, function () { 20844 $(this).remove(); 20845 }); 20846 } 20847 } 20848 } 20849 } 20850 20851 if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) { 20852 that.$button.focus(); 20853 } else if (that.options.liveSearch) { 20854 that.$searchbox.focus(); 20855 } 20856 20857 // Trigger select 'change' 20858 if (triggerChange) { 20859 if ((prevValue != getSelectValues(that.$element[0]) && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) { 20860 // $option.prop('selected') is current option state (selected/unselected). prevValue is the value of the select prior to being changed. 20861 changedArguments = [clickedIndex, $option.prop('selected'), prevValue]; 20862 that.$element 20863 .triggerNative('change'); 20864 } 20865 } 20866 } 20867 }); 20868 20869 this.$menu.on('click', 'li.' + classNames.DISABLED + ' a, .' + classNames.POPOVERHEADER + ', .' + classNames.POPOVERHEADER + ' :not(.close)', function (e) { 20870 if (e.currentTarget == this) { 20871 e.preventDefault(); 20872 e.stopPropagation(); 20873 if (that.options.liveSearch && !$(e.target).hasClass('close')) { 20874 that.$searchbox.focus(); 20875 } else { 20876 that.$button.focus(); 20877 } 20878 } 20879 }); 20880 20881 this.$menuInner.on('click', '.divider, .dropdown-header', function (e) { 20882 e.preventDefault(); 20883 e.stopPropagation(); 20884 if (that.options.liveSearch) { 20885 that.$searchbox.focus(); 20886 } else { 20887 that.$button.focus(); 20888 } 20889 }); 20890 20891 this.$menu.on('click', '.' + classNames.POPOVERHEADER + ' .close', function () { 20892 that.$button.click(); 20893 }); 20894 20895 this.$searchbox.on('click', function (e) { 20896 e.stopPropagation(); 20897 }); 20898 20899 this.$menu.on('click', '.actions-btn', function (e) { 20900 if (that.options.liveSearch) { 20901 that.$searchbox.focus(); 20902 } else { 20903 that.$button.focus(); 20904 } 20905 20906 e.preventDefault(); 20907 e.stopPropagation(); 20908 20909 if ($(this).hasClass('bs-select-all')) { 20910 that.selectAll(); 20911 } else { 20912 that.deselectAll(); 20913 } 20914 }); 20915 20916 this.$element.on({ 20917 'change': function () { 20918 that.render(); 20919 that.$element.trigger('changed' + EVENT_KEY, changedArguments); 20920 changedArguments = null; 20921 }, 20922 'focus': function () { 20923 if (!that.options.mobile) that.$button.focus(); 20924 } 20925 }); 20926 }, 20927 20928 liveSearchListener: function () { 20929 var that = this, 20930 noResults = document.createElement('li'); 20931 20932 this.$button.on('click.bs.dropdown.data-api', function () { 20933 if (!!that.$searchbox.val()) { 20934 that.$searchbox.val(''); 20935 } 20936 }); 20937 20938 this.$searchbox.on('click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api', function (e) { 20939 e.stopPropagation(); 20940 }); 20941 20942 this.$searchbox.on('input propertychange', function () { 20943 var searchValue = that.$searchbox.val(); 20944 20945 that.selectpicker.search.map.newIndex = {}; 20946 that.selectpicker.search.map.originalIndex = {}; 20947 that.selectpicker.search.elements = []; 20948 that.selectpicker.search.data = []; 20949 20950 if (searchValue) { 20951 var i, 20952 searchMatch = [], 20953 q = searchValue.toUpperCase(), 20954 cache = {}, 20955 cacheArr = [], 20956 searchStyle = that._searchStyle(), 20957 normalizeSearch = that.options.liveSearchNormalize; 20958 20959 if (normalizeSearch) q = normalizeToBase(q); 20960 20961 that._$lisSelected = that.$menuInner.find('.selected'); 20962 20963 for (var i = 0; i < that.selectpicker.main.data.length; i++) { 20964 var li = that.selectpicker.main.data[i]; 20965 20966 if (!cache[i]) { 20967 cache[i] = stringSearch(li, q, searchStyle, normalizeSearch); 20968 } 20969 20970 if (cache[i] && li.headerIndex !== undefined && cacheArr.indexOf(li.headerIndex) === -1) { 20971 if (li.headerIndex > 0) { 20972 cache[li.headerIndex - 1] = true; 20973 cacheArr.push(li.headerIndex - 1); 20974 } 20975 20976 cache[li.headerIndex] = true; 20977 cacheArr.push(li.headerIndex); 20978 20979 cache[li.lastIndex + 1] = true; 20980 } 20981 20982 if (cache[i] && li.type !== 'optgroup-label') cacheArr.push(i); 20983 } 20984 20985 for (var i = 0, cacheLen = cacheArr.length; i < cacheLen; i++) {
20986 var index = cacheArr[i], 20987 prevIndex = cacheArr[i - 1], 20988 li = that.selectpicker.main.data[index], 20989 liPrev = that.selectpicker.main.data[prevIndex]; 20990 20991 if (li.type !== 'divider' || (li.type === 'divider' && liPrev && liPrev.type !== 'divider' && cacheLen - 1 !== i)) { 20992 that.selectpicker.search.data.push(li); 20993 searchMatch.push(that.selectpicker.main.elements[index]); 20994 20995 if (li.hasOwnProperty('originalIndex')) { 20996 that.selectpicker.search.map.newIndex[li.originalIndex] = searchMatch.length - 1; 20997 that.selectpicker.search.map.originalIndex[searchMatch.length - 1] = li.originalIndex; 20998 } 20999 } 21000 } 21001 21002 that.activeIndex = undefined; 21003 that.noScroll = true; 21004 that.$menuInner.scrollTop(0); 21005 that.selectpicker.search.elements = searchMatch; 21006 that.createView(true); 21007 21008 if (!searchMatch.length) { 21009 noResults.className = 'no-results'; 21010 noResults.innerHTML = that.options.noneResultsText.replace('{0}', '"' + htmlEscape(searchValue) + '"'); 21011 that.$menuInner[0].firstChild.appendChild(noResults); 21012 } 21013 } else { 21014 that.$menuInner.scrollTop(0); 21015 that.createView(false); 21016 } 21017 }); 21018 }, 21019 21020 _searchStyle: function () { 21021 return this.options.liveSearchStyle || 'contains'; 21022 }, 21023 21024 val: function (value) { 21025 if (typeof value !== 'undefined') { 21026 this.$element 21027 .val(value) 21028 .triggerNative('change'); 21029 21030 return this.$element; 21031 } else { 21032 return this.$element.val(); 21033 } 21034 }, 21035 21036 changeAll: function (status) { 21037 if (!this.multiple) return; 21038 if (typeof status === 'undefined') status = true; 21039 21040 var $selectOptions = this.$element.find('option'), 21041 previousSelected = 0, 21042 currentSelected = 0, 21043 prevValue = getSelectValues(this.$element[0]); 21044 21045 this.$element.addClass('bs-select-hidden'); 21046 21047 for (var i = 0; i < this.selectpicker.current.elements.length; i++) { 21048 var liData = this.selectpicker.current.data[i], 21049 index = this.selectpicker.current.map.originalIndex[i], // faster than $(li).data('originalIndex') 21050 option = $selectOptions[index]; 21051 21052 if (option && !option.disabled && liData.type !== 'divider') { 21053 if (option.selected) previousSelected++; 21054 option.selected = status; 21055 if (option.selected) currentSelected++; 21056 } 21057 } 21058 21059 this.$element.removeClass('bs-select-hidden'); 21060 21061 if (previousSelected === currentSelected) return; 21062 21063 this.setOptionStatus(); 21064 21065 this.togglePlaceholder(); 21066 21067 changedArguments = [null, null, prevValue]; 21068 21069 this.$element 21070 .triggerNative('change'); 21071 }, 21072 21073 selectAll: function () { 21074 return this.changeAll(true); 21075 }, 21076 21077 deselectAll: function () { 21078 return this.changeAll(false); 21079 }, 21080 21081 toggle: function (e) { 21082 e = e || window.event; 21083 21084 if (e) e.stopPropagation(); 21085 21086 this.$button.trigger('click.bs.dropdown.data-api'); 21087 }, 21088 21089 keydown: function (e) { 21090 var $this = $(this), 21091 isToggle = $this.hasClass('dropdown-toggle'), 21092 $parent = isToggle ? $this.closest('.dropdown') : $this.closest(Selector.MENU), 21093 that = $parent.data('this'), 21094 $items = that.findLis(), 21095 index, 21096 isActive, 21097 liActive, 21098 activeLi, 21099 offset, 21100 updateScroll = false, 21101 downOnTab = e.which === keyCodes.TAB && !isToggle && !that.options.selectOnTab, 21102 isArrowKey = REGEXP_ARROW.test(e.which) || downOnTab, 21103 scrollTop = that.$menuInner[0].scrollTop, 21104 isVirtual = that.isVirtual(), 21105 position0 = isVirtual === true ? that.selectpicker.view.position0 : 0; 21106 21107 isActive = that.$newElement.hasClass(classNames.SHOW); 21108 21109 if ( 21110 !isActive && 21111 ( 21112 isArrowKey || 21113 (e.which >= 48 && e.which <= 57) || 21114 (e.which >= 96 && e.which <= 105) || 21115 (e.which >= 65 && e.which <= 90) 21116 ) 21117 ) { 21118 that.$button.trigger('click.bs.dropdown.data-api'); 21119 } 21120 21121 if (e.which === keyCodes.ESCAPE && isActive) { 21122 e.preventDefault(); 21123 that.$button.trigger('click.bs.dropdown.data-api').focus(); 21124 } 21125 21126 if (isArrowKey) { // if up or down 21127 if (!$items.length) return; 21128 21129 // $items.index/.filter is too slow with a large list and no virtual scroll 21130 index = isVirtual === true ? $items.index($items.filter('.active')) : that.selectpicker.current.map.newIndex[that.activeIndex]; 21131 21132 if (index === undefined) index = -1; 21133 21134 if (index !== -1) { 21135 liActive = that.selectpicker.current.elements[index + position0]; 21136 liActive.classList.remove('active'); 21137 if (liActive.firstChild) liActive.firstChild.classList.remove('active'); 21138 } 21139 21140 if (e.which === keyCodes.ARROW_UP) { // up 21141 if (index !== -1) index--; 21142 if (index + position0 < 0) index += $items.length; 21143 21144 if (!that.selectpicker.view.canHighlight[index + position0]) { 21145 index = that.selectpicker.view.canHighlight.slice(0, index + position0).lastIndexOf(true) - position0; 21146 if (index === -1) index = $items.length - 1; 21147 } 21148 } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down 21149 index++; 21150 if (index + position0 >
vendor: 10,123 bytes, lines 21150-21460
21150= that.selectpicker.view.canHighlight.length) index = 0; 21151 21152 if (!that.selectpicker.view.canHighlight[index + position0]) { 21153 index = index + 1 + that.selectpicker.view.canHighlight.slice(index + position0 + 1).indexOf(true); 21154 } 21155 } 21156 21157 e.preventDefault(); 21158 21159 var liActiveIndex = position0 + index; 21160 21161 if (e.which === keyCodes.ARROW_UP) { // up 21162 // scroll to bottom and highlight last option 21163 if (position0 === 0 && index === $items.length - 1) { 21164 that.$menuInner[0].scrollTop = that.$menuInner[0].scrollHeight; 21165 21166 liActiveIndex = that.selectpicker.current.elements.length - 1; 21167 } else { 21168 activeLi = that.selectpicker.current.data[liActiveIndex]; 21169 offset = activeLi.position - activeLi.height; 21170 21171 updateScroll = offset < scrollTop; 21172 } 21173 } else if (e.which === keyCodes.ARROW_DOWN || downOnTab) { // down 21174 // scroll to top and highlight first option 21175 if (index === 0) { 21176 that.$menuInner[0].scrollTop = 0; 21177 21178 liActiveIndex = 0; 21179 } else { 21180 activeLi = that.selectpicker.current.data[liActiveIndex]; 21181 offset = activeLi.position - that.sizeInfo.menuInnerHeight; 21182 21183 updateScroll = offset > scrollTop; 21184 } 21185 } 21186 21187 liActive = that.selectpicker.current.elements[liActiveIndex]; 21188 21189 if (liActive) { 21190 liActive.classList.add('active'); 21191 if (liActive.firstChild) liActive.firstChild.classList.add('active'); 21192 } 21193 21194 that.activeIndex = that.selectpicker.current.map.originalIndex[liActiveIndex]; 21195 21196 that.selectpicker.view.currentActive = liActive; 21197 21198 if (updateScroll) that.$menuInner[0].scrollTop = offset; 21199 21200 if (that.options.liveSearch) { 21201 that.$searchbox.focus(); 21202 } else { 21203 $this.focus(); 21204 } 21205 } else if ( 21206 (!$this.is('input') && !REGEXP_TAB_OR_ESCAPE.test(e.which)) || 21207 (e.which === keyCodes.SPACE && that.selectpicker.keydown.keyHistory) 21208 ) { 21209 var searchMatch, 21210 matches = [], 21211 keyHistory; 21212 21213 e.preventDefault(); 21214 21215 that.selectpicker.keydown.keyHistory += keyCodeMap[e.which]; 21216 21217 if (that.selectpicker.keydown.resetKeyHistory.cancel) clearTimeout(that.selectpicker.keydown.resetKeyHistory.cancel); 21218 that.selectpicker.keydown.resetKeyHistory.cancel = that.selectpicker.keydown.resetKeyHistory.start(); 21219 21220 keyHistory = that.selectpicker.keydown.keyHistory; 21221 21222 // if all letters are the same, set keyHistory to just the first character when searching 21223 if (/^(.)\1+$/.test(keyHistory)) { 21224 keyHistory = keyHistory.charAt(0); 21225 } 21226 21227 // find matches 21228 for (var i = 0; i < that.selectpicker.current.data.length; i++) { 21229 var li = that.selectpicker.current.data[i], 21230 hasMatch; 21231 21232 hasMatch = stringSearch(li, keyHistory, 'startsWith', true); 21233 21234 if (hasMatch && that.selectpicker.view.canHighlight[i]) { 21235 li.index = i; 21236 matches.push(li.originalIndex); 21237 } 21238 } 21239 21240 if (matches.length) { 21241 var matchIndex = 0; 21242 21243 $items.removeClass('active').find('a').removeClass('active'); 21244 21245 // either only one key has been pressed or they are all the same key 21246 if (keyHistory.length === 1) { 21247 matchIndex = matches.indexOf(that.activeIndex); 21248 21249 if (matchIndex === -1 || matchIndex === matches.length - 1) { 21250 matchIndex = 0; 21251 } else { 21252 matchIndex++; 21253 } 21254 } 21255 21256 searchMatch = that.selectpicker.current.map.newIndex[matches[matchIndex]]; 21257 21258 activeLi = that.selectpicker.current.data[searchMatch]; 21259 21260 if (scrollTop - activeLi.position > 0) { 21261 offset = activeLi.position - activeLi.height; 21262 updateScroll = true; 21263 } else { 21264 offset = activeLi.position - that.sizeInfo.menuInnerHeight; 21265 // if the option is already visible at the current scroll position, just keep it the same 21266 updateScroll = activeLi.position > scrollTop + that.sizeInfo.menuInnerHeight; 21267 } 21268 21269 liActive = that.selectpicker.current.elements[searchMatch]; 21270 liActive.classList.add('active'); 21271 if (liActive.firstChild) liActive.firstChild.classList.add('active'); 21272 that.activeIndex = matches[matchIndex]; 21273 21274 liActive.firstChild.focus(); 21275 21276 if (updateScroll) that.$menuInner[0].scrollTop = offset; 21277 21278 $this.focus(); 21279 } 21280 } 21281 21282 // Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu. 21283 if ( 21284 isActive && 21285 ( 21286 (e.which === keyCodes.SPACE && !that.selectpicker.keydown.keyHistory) || 21287 e.which === keyCodes.ENTER || 21288 (e.which === keyCodes.TAB && that.options.selectOnTab) 21289 ) 21290 ) { 21291 if (e.which !== keyCodes.SPACE) e.preventDefault(); 21292 21293 if (!that.options.liveSearch || e.which !== keyCodes.SPACE) { 21294 that.$menuInner.find('.active a').trigger('click', true); // retain active class 21295 $this.focus(); 21296 21297 if (!that.options.liveSearch) { 21298 // Prevent screen from scrolling if the user hits the spacebar 21299 e.preventDefault(); 21300 // Fixes spacebar selection of dropdown items in FF & IE 21301 $(document).data('spaceSelect', true); 21302 } 21303 } 21304 } 21305 }, 21306 21307 mobile: function () { 21308 this.$element.addClass('mobile-device'); 21309 }, 21310 21311 refresh: function () { 21312 // update options if data attributes have been changed 21313 var config = $.extend({}, this.options, this.$element.data()); 21314 this.options = config; 21315 21316 this.selectpicker.main.map.newIndex = {}; 21317 this.selectpicker.main.map.originalIndex = {}; 21318 this.createLi(); 21319 this.checkDisabled(); 21320 this.render(); 21321 this.setStyle(); 21322 this.setWidth(); 21323 21324 this.setSize(true); 21325 21326 this.$element.trigger('refreshed' + EVENT_KEY); 21327 }, 21328 21329 hide: function () { 21330 this.$newElement.hide(); 21331 }, 21332 21333 show: function () { 21334 this.$newElement.show(); 21335 }, 21336 21337 remove: function () { 21338 this.$newElement.remove(); 21339 this.$element.remove(); 21340 }, 21341 21342 destroy: function () { 21343 this.$newElement.before(this.$element).remove(); 21344 21345 if (this.$bsContainer) { 21346 this.$bsContainer.remove(); 21347 } else { 21348 this.$menu.remove(); 21349 } 21350 21351 this.$element 21352 .off(EVENT_KEY) 21353 .removeData('selectpicker') 21354 .removeClass('bs-select-hidden selectpicker'); 21355 21356 $(window).off(EVENT_KEY + '.' + this.selectId); 21357 } 21358 }; 21359 21360 // SELECTPICKER PLUGIN DEFINITION 21361 // ============================== 21362 function Plugin (option) { 21363 // get the args of the outer function.. 21364 var args = arguments; 21365 // The arguments of the function are explicitly re-defined from the argument list, because the shift causes them 21366 // to get lost/corrupted in android 2.3 and IE9 #715 #775 21367 var _option = option; 21368 21369 [].shift.apply(args); 21370 21371 // if the version was not set successfully 21372 if (!version.success) { 21373 // try to retreive it again 21374 try { 21375 version.full = ($.fn.dropdown.Constructor.VERSION || '').split(' ')[0].split('.'); 21376 } catch (err) { 21377 // fall back to use BootstrapVersion 21378 version.full = Selectpicker.BootstrapVersion.split(' ')[0].split('.'); 21379 } 21380 21381 version.major = version.full[0]; 21382 version.success = true; 21383 21384 if (version.major === '4') { 21385 classNames.DIVIDER = 'dropdown-divider'; 21386 classNames.SHOW = 'show'; 21387 classNames.BUTTONCLASS = 'btn-light'; 21388 Selectpicker.DEFAULTS.style = classNames.BUTTONCLASS = 'btn-light'; 21389 classNames.POPOVERHEADER = 'popover-header'; 21390 } 21391 } 21392 21393 var value; 21394 var chain = this.each(function () { 21395 var $this = $(this); 21396 if ($this.is('select')) { 21397 var data = $this.data('selectpicker'), 21398 options = typeof _option == 'object' && _option; 21399 21400 if (!data) { 21401 var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options); 21402 config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template); 21403 $this.data('selectpicker', (data = new Selectpicker(this, config))); 21404 } else if (options) { 21405 for (var i in options) { 21406 if (options.hasOwnProperty(i)) { 21407 data.options[i] = options[i]; 21408 } 21409 } 21410 } 21411 21412 if (typeof _option == 'string') { 21413 if (data[_option] instanceof Function) { 21414 value = data[_option].apply(data, args); 21415 } else { 21416 value = data.options[_option]; 21417 } 21418 } 21419 } 21420 }); 21421 21422 if (typeof value !== 'undefined') { 21423 // noinspection JSUnusedAssignment 21424 return value; 21425 } else { 21426 return chain; 21427 } 21428 } 21429 21430 var old = $.fn.selectpicker; 21431 $.fn.selectpicker = Plugin; 21432 $.fn.selectpicker.Constructor = Selectpicker; 21433 21434 // SELECTPICKER NO CONFLICT 21435 // ======================== 21436 $.fn.selectpicker.noConflict = function () { 21437 $.fn.selectpicker = old; 21438 return this; 21439 }; 21440 21441 $(document) 21442 .off('keydown.bs.dropdown.data-api') 21443 .on('keydown' + EVENT_KEY, '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', Selectpicker.prototype.keydown) 21444 .on('focusin.modal', '.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bootstrap-select .bs-searchbox input', function (e) { 21445 e.stopPropagation(); 21446 }); 21447 21448 // SELECTPICKER DATA-API 21449 // ===================== 21450 $(window).on('load' + EVENT_KEY + '.data-api', function () { 21451 $('.selectpicker').each(function () { 21452 var $selectpicker = $(this); 21453 Plugin.call($selectpicker, $selectpicker.data()); 21454 }) 21455 }); 21456})(jQuery); 21457 21458 21459})); 21460
vendor: 32,123 bytes, lines 21461-22346
21461/*! 21462 * typeahead.js 0.11.1 21463 * https://github.com/twitter/typeahead.js 21464 * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT 21465 */ 21466 21467(function(root, factory) { 21468 if (typeof define === "function" && define.amd) { 21469 define("bloodhound", [ "jquery" ], function(a0) { 21470 return root["Bloodhound"] = factory(a0); 21471 }); 21472 } else if (typeof exports === "object") { 21473 module.exports = factory(require("jquery")); 21474 } else { 21475 root["Bloodhound"] = factory(jQuery); 21476 } 21477})(this, function($) { 21478 var _ = function() { 21479 "use strict"; 21480 return { 21481 isMsie: function() { 21482 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 21483 }, 21484 isBlankString: function(str) { 21485 return !str || /^\s*$/.test(str); 21486 }, 21487 escapeRegExChars: function(str) { 21488 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 21489 }, 21490 isString: function(obj) { 21491 return typeof obj === "string"; 21492 }, 21493 isNumber: function(obj) { 21494 return typeof obj === "number"; 21495 }, 21496 isArray: $.isArray, 21497 isFunction: $.isFunction, 21498 isObject: $.isPlainObject, 21499 isUndefined: function(obj) { 21500 return typeof obj === "undefined"; 21501 }, 21502 isElement: function(obj) { 21503 return !!(obj && obj.nodeType === 1); 21504 }, 21505 isJQuery: function(obj) { 21506 return obj instanceof $; 21507 }, 21508 toStr: function toStr(s) { 21509 return _.isUndefined(s) || s === null ? "" : s + ""; 21510 }, 21511 bind: $.proxy, 21512 each: function(collection, cb) { 21513 $.each(collection, reverseArgs); 21514 function reverseArgs(index, value) { 21515 return cb(value, index); 21516 } 21517 }, 21518 map: $.map, 21519 filter: $.grep, 21520 every: function(obj, test) { 21521 var result = true; 21522 if (!obj) { 21523 return result; 21524 } 21525 $.each(obj, function(key, val) { 21526 if (!(result = test.call(null, val, key, obj))) { 21527 return false; 21528 } 21529 }); 21530 return !!result; 21531 }, 21532 some: function(obj, test) { 21533 var result = false; 21534 if (!obj) { 21535 return result; 21536 } 21537 $.each(obj, function(key, val) { 21538 if (result = test.call(null, val, key, obj)) { 21539 return false; 21540 } 21541 }); 21542 return !!result; 21543 }, 21544 mixin: $.extend, 21545 identity: function(x) { 21546 return x; 21547 }, 21548 clone: function(obj) { 21549 return $.extend(true, {}, obj); 21550 }, 21551 getIdGenerator: function() { 21552 var counter = 0; 21553 return function() { 21554 return counter++; 21555 }; 21556 }, 21557 templatify: function templatify(obj) { 21558 return $.isFunction(obj) ? obj : template; 21559 function template() { 21560 return String(obj); 21561 } 21562 }, 21563 defer: function(fn) { 21564 setTimeout(fn, 0); 21565 }, 21566 debounce: function(func, wait, immediate) { 21567 var timeout, result; 21568 return function() { 21569 var context = this, args = arguments, later, callNow; 21570 later = function() { 21571 timeout = null; 21572 if (!immediate) { 21573 result = func.apply(context, args); 21574 } 21575 }; 21576 callNow = immediate && !timeout; 21577 clearTimeout(timeout); 21578 timeout = setTimeout(later, wait); 21579 if (callNow) { 21580 result = func.apply(context, args); 21581 } 21582 return result; 21583 }; 21584 }, 21585 throttle: function(func, wait) { 21586 var context, args, timeout, result, previous, later; 21587 previous = 0; 21588 later = function() { 21589 previous = new Date(); 21590 timeout = null; 21591 result = func.apply(context, args); 21592 }; 21593 return function() { 21594 var now = new Date(), remaining = wait - (now - previous); 21595 context = this; 21596 args = arguments; 21597 if (remaining <= 0) { 21598 clearTimeout(timeout); 21599 timeout = null; 21600 previous = now; 21601 result = func.apply(context, args); 21602 } else if (!timeout) { 21603 timeout = setTimeout(later, remaining); 21604 } 21605 return result; 21606 }; 21607 }, 21608 stringify: function(val) { 21609 return _.isString(val) ? val : JSON.stringify(val); 21610 }, 21611 noop: function() {} 21612 }; 21613 }(); 21614 var VERSION = "0.11.1"; 21615 var tokenizers = function() { 21616 "use strict"; 21617 return { 21618 nonword: nonword, 21619 whitespace: whitespace, 21620 obj: { 21621 nonword: getObjTokenizer(nonword), 21622 whitespace: getObjTokenizer(whitespace) 21623 } 21624 }; 21625 function whitespace(str) { 21626 str = _.toStr(str); 21627 return str ? str.split(/\s+/) : []; 21628 } 21629 function nonword(str) { 21630 str = _.toStr(str); 21631 return str ? str.split(/\W+/) : []; 21632 } 21633 function getObjTokenizer(tokenizer) { 21634 return function setKey(keys) { 21635 keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0); 21636 return function tokenize(o) { 21637 var tokens = []; 21638 _.each(keys, function(k) { 21639 tokens = tokens.concat(tokenizer(_.toStr(o[k]))); 21640 }); 21641 return tokens; 21642 }; 21643 }; 21644 } 21645 }(); 21646 var LruCache = function() { 21647 "use strict"; 21648 function LruCache(maxSize) { 21649 this.maxSize = _.isNumber(maxSize) ? maxSize : 100; 21650 this.reset(); 21651 if (this.maxSize <= 0) { 21652 this.set = this.get = $.noop; 21653 } 21654 } 21655 _.mixin(LruCache.prototype, { 21656 set: function set(key, val) { 21657 var tailItem = this.list.tail, node; 21658 if (this.size >= this.maxSize) { 21659 this.list.remove(tailItem); 21660 delete this.hash[tailItem.key]; 21661 this.size--; 21662 } 21663 if (node = this.hash[key]) { 21664 node.val = val; 21665 this.list.moveToFront(node); 21666 } else { 21667 node = new Node(key, val); 21668 this.list.add(node); 21669 this.hash[key] = node; 21670 this.size++; 21671 } 21672 }, 21673 get: function get(key) { 21674 var node = this.hash[key]; 21675 if (node) { 21676 this.list.moveToFront(node); 21677 return node.val; 21678 } 21679 }, 21680 reset: function reset() { 21681 this.size = 0; 21682 this.hash = {}; 21683 this.list = new List(); 21684 } 21685 }); 21686 function List() { 21687 this.head = this.tail = null; 21688 } 21689 _.mixin(List.prototype, { 21690 add: function add(node) { 21691 if (this.head) { 21692 node.next = this.head; 21693 this.head.prev = node; 21694 } 21695 this.head = node; 21696 this.tail = this.tail || node; 21697 }, 21698 remove: function remove(node) { 21699 node.prev ? node.prev.next = node.next : this.head = node.next; 21700 node.next ? node.next.prev = node.prev : this.tail = node.prev; 21701 }, 21702 moveToFront: function(node) { 21703 this.remove(node); 21704 this.add(node); 21705 } 21706 }); 21707 function Node(key, val) { 21708 this.key = key; 21709 this.val = val; 21710 this.prev = this.next = null; 21711 } 21712 return LruCache; 21713 }(); 21714 var PersistentStorage = function() { 21715 "use strict"; 21716 var LOCAL_STORAGE; 21717 try { 21718 LOCAL_STORAGE = window.localStorage; 21719 LOCAL_STORAGE.setItem("~~~", "!"); 21720 LOCAL_STORAGE.removeItem("~~~"); 21721 } catch (err) { 21722 LOCAL_STORAGE = null; 21723 } 21724 function PersistentStorage(namespace, override) { 21725 this.prefix = [ "__", namespace, "__" ].join(""); 21726 this.ttlKey = "__ttl__"; 21727 this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix)); 21728 this.ls = override || LOCAL_STORAGE; 21729 !this.ls && this._noop(); 21730 } 21731 _.mixin(PersistentStorage.prototype, { 21732 _prefix: function(key) { 21733 return this.prefix + key; 21734 }, 21735 _ttlKey: function(key) { 21736 return this._prefix(key) + this.ttlKey; 21737 }, 21738 _noop: function() { 21739 this.get = this.set = this.remove = this.clear = this.isExpired = _.noop; 21740 }, 21741 _safeSet: function(key, val) { 21742 try { 21743 this.ls.setItem(key, val); 21744 } catch (err) { 21745 if (err.name === "QuotaExceededError") { 21746 this.clear(); 21747 this._noop(); 21748 } 21749 } 21750 }, 21751 get: function(key) { 21752 if (this.isExpired(key)) { 21753 this.remove(key); 21754 } 21755 return decode(this.ls.getItem(this._prefix(key))); 21756 }, 21757 set: function(key, val, ttl) { 21758 if (_.isNumber(ttl)) { 21759 this._safeSet(this._ttlKey(key), encode(now() + ttl)); 21760 } else { 21761 this.ls.removeItem(this._ttlKey(key)); 21762 } 21763 return this._safeSet(this._prefix(key), encode(val)); 21764 }, 21765 remove: function(key) { 21766 this.ls.removeItem(this._ttlKey(key)); 21767 this.ls.removeItem(this._prefix(key)); 21768 return this; 21769 }, 21770 clear: function() { 21771 var i, keys = gatherMatchingKeys(this.keyMatcher); 21772 for (i = keys.length; i--; ) { 21773 this.remove(keys[i]); 21774 } 21775 return this; 21776 }, 21777 isExpired: function(key) { 21778 var ttl = decode(this.ls.getItem(this._ttlKey(key))); 21779 return _.isNumber(ttl) && now() > ttl ? true : false; 21780 } 21781 }); 21782 return PersistentStorage; 21783 function now() { 21784 return new Date().getTime(); 21785 } 21786 function encode(val) { 21787 return JSON.stringify(_.isUndefined(val) ? null : val); 21788 } 21789 function decode(val) { 21790 return $.parseJSON(val); 21791 } 21792 function gatherMatchingKeys(keyMatcher) { 21793 var i, key, keys = [], len = LOCAL_STORAGE.length; 21794 for (i = 0; i < len; i++) { 21795 if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) { 21796 keys.push(key.replace(keyMatcher, "")); 21797 } 21798 } 21799 return keys; 21800 } 21801 }(); 21802 var Transport = function() { 21803 "use strict"; 21804 var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10); 21805 function Transport(o) { 21806 o = o || {}; 21807 this.cancelled = false; 21808 this.lastReq = null; 21809 this._send = o.transport; 21810 this._get = o.limiter ? o.limiter(this._get) : this._get; 21811 this._cache = o.cache === false ? new LruCache(0) : sharedCache; 21812 } 21813 Transport.setMaxPendingRequests = function setMaxPendingRequests(num) { 21814 maxPendingRequests = num; 21815 }; 21816 Transport.resetCache = function resetCache() { 21817 sharedCache.reset(); 21818 }; 21819 _.mixin(Transport.prototype, { 21820 _fingerprint: function fingerprint(o) { 21821 o = o || {}; 21822 return o.url + o.type + $.param(o.data || {}); 21823 }, 21824 _get: function(o, cb) { 21825 var that = this, fingerprint, jqXhr; 21826 fingerprint = this._fingerprint(o); 21827 if (this.cancelled || fingerprint !== this.lastReq) { 21828 return; 21829 } 21830 if (jqXhr = pendingRequests[fingerprint]) { 21831 jqXhr.done(done).fail(fail); 21832 } else if (pendingRequestsCount < maxPendingRequests) { 21833 pendingRequestsCount++; 21834 pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always); 21835 } else { 21836 this.onDeckRequestArgs = [].slice.call(arguments, 0); 21837 } 21838 function done(resp) { 21839 cb(null, resp); 21840 that._cache.set(fingerprint, resp); 21841 } 21842 function fail() { 21843 cb(true); 21844 } 21845 function always() { 21846 pendingRequestsCount--; 21847 delete pendingRequests[fingerprint]; 21848 if (that.onDeckRequestArgs) { 21849 that._get.apply(that, that.onDeckRequestArgs); 21850 that.onDeckRequestArgs = null; 21851 } 21852 } 21853 }, 21854 get: function(o, cb) { 21855 var resp, fingerprint; 21856 cb = cb || $.noop; 21857 o = _.isString(o) ? { 21858 url: o 21859 } : o || {}; 21860 fingerprint = this._fingerprint(o); 21861 this.cancelled = false; 21862 this.lastReq = fingerprint; 21863 if (resp = this._cache.get(fingerprint)) { 21864 cb(null, resp); 21865 } else { 21866 this._get(o, cb); 21867 } 21868 }, 21869 cancel: function() { 21870 this.cancelled = true; 21871 } 21872 }); 21873 return Transport; 21874 }(); 21875 var SearchIndex = window.SearchIndex = function() { 21876 "use strict"; 21877 var CHILDREN = "c", IDS = "i"; 21878 function SearchIndex(o) { 21879 o = o || {}; 21880 if (!o.datumTokenizer || !o.queryTokenizer) { 21881 $.error("datumTokenizer and queryTokenizer are both required"); 21882 } 21883 this.identify = o.identify || _.stringify; 21884 this.datumTokenizer = o.datumTokenizer; 21885 this.queryTokenizer = o.queryTokenizer; 21886 this.reset(); 21887 } 21888 _.mixin(SearchIndex.prototype, { 21889 bootstrap: function bootstrap(o) { 21890 this.datums = o.datums; 21891 this.trie = o.trie; 21892 }, 21893 add: function(data) { 21894 var that = this; 21895 data = _.isArray(data) ? data : [ data ]; 21896 _.each(data, function(datum) { 21897 var id, tokens; 21898 that.datums[id = that.identify(datum)] = datum; 21899 tokens = normalizeTokens(that.datumTokenizer(datum)); 21900 _.each(tokens, function(token) { 21901 var node, chars, ch; 21902 node = that.trie; 21903 chars = token.split(""); 21904 while (ch = chars.shift()) { 21905 node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode()); 21906 node[IDS].push(id); 21907 } 21908 }); 21909 }); 21910 }, 21911 get: function get(ids) { 21912 var that = this; 21913 return _.map(ids, function(id) { 21914 return that.datums[id]; 21915 }); 21916 }, 21917 search: function search(query) { 21918 var that = this, tokens, matches; 21919 tokens = normalizeTokens(this.queryTokenizer(query)); 21920 _.each(tokens, function(token) { 21921 var node, chars, ch, ids; 21922 if (matches && matches.length === 0) { 21923 return false; 21924 } 21925 node = that.trie; 21926 chars = token.split(""); 21927 while (node && (ch = chars.shift())) { 21928 node = node[CHILDREN][ch]; 21929 } 21930 if (node && chars.length === 0) { 21931 ids = node[IDS].slice(0); 21932 matches = matches ? getIntersection(matches, ids) : ids; 21933 } else { 21934 matches = []; 21935 return false; 21936 } 21937 }); 21938 return matches ? _.map(unique(matches), function(id) { 21939 return that.datums[id]; 21940 }) : []; 21941 }, 21942 all: function all() { 21943 var values = []; 21944 for (var key in this.datums) { 21945 values.push(this.datums[key]); 21946 } 21947 return values; 21948 }, 21949 reset: function reset() { 21950 this.datums = {}; 21951 this.trie = newNode(); 21952 }, 21953 serialize: function serialize() { 21954 return { 21955 datums: this.datums, 21956 trie: this.trie 21957 }; 21958 } 21959 }); 21960 return SearchIndex; 21961 function normalizeTokens(tokens) { 21962 tokens = _.filter(tokens, function(token) { 21963 return !!token; 21964 }); 21965 tokens = _.map(tokens, function(token) { 21966 return token.toLowerCase(); 21967 }); 21968 return tokens; 21969 } 21970 function newNode() { 21971 var node = {}; 21972 node[IDS] = []; 21973 node[CHILDREN] = {}; 21974 return node; 21975 } 21976 function unique(array) { 21977 var seen = {}, uniques = []; 21978 for (var i = 0, len = array.length; i < len; i++) { 21979 if (!seen[array[i]]) { 21980 seen[array[i]] = true; 21981 uniques.push(array[i]); 21982 } 21983 } 21984 return uniques; 21985 } 21986 function getIntersection(arrayA, arrayB) { 21987 var ai = 0, bi = 0, intersection = []; 21988 arrayA = arrayA.sort(); 21989 arrayB = arrayB.sort(); 21990 var lenArrayA = arrayA.length, lenArrayB = arrayB.length; 21991 while (ai < lenArrayA && bi < lenArrayB) { 21992 if (arrayA[ai] < arrayB[bi]) { 21993 ai++; 21994 } else if (arrayA[ai] > arrayB[bi]) { 21995 bi++; 21996 } else { 21997 intersection.push(arrayA[ai]); 21998 ai++; 21999 bi++; 22000 } 22001 } 22002 return intersection; 22003 } 22004 }(); 22005 var Prefetch = function() { 22006 "use strict"; 22007 var keys; 22008 keys = { 22009 data: "data", 22010 protocol: "protocol", 22011 thumbprint: "thumbprint" 22012 }; 22013 function Prefetch(o) { 22014 this.url = o.url; 22015 this.ttl = o.ttl; 22016 this.cache = o.cache; 22017 this.prepare = o.prepare; 22018 this.transform = o.transform; 22019 this.transport = o.transport; 22020 this.thumbprint = o.thumbprint; 22021 this.storage = new PersistentStorage(o.cacheKey); 22022 } 22023 _.mixin(Prefetch.prototype, { 22024 _settings: function settings() { 22025 return { 22026 url: this.url, 22027 type: "GET", 22028 dataType: "json" 22029 }; 22030 }, 22031 store: function store(data) { 22032 if (!this.cache) { 22033 return; 22034 } 22035 this.storage.set(keys.data, data, this.ttl); 22036 this.storage.set(keys.protocol, location.protocol, this.ttl); 22037 this.storage.set(keys.thumbprint, this.thumbprint, this.ttl); 22038 }, 22039 fromCache: function fromCache() { 22040 var stored = {}, isExpired; 22041 if (!this.cache) { 22042 return null; 22043 } 22044 stored.data = this.storage.get(keys.data); 22045 stored.protocol = this.storage.get(keys.protocol); 22046 stored.thumbprint = this.storage.get(keys.thumbprint); 22047 isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol; 22048 return stored.data && !isExpired ? stored.data : null; 22049 }, 22050 fromNetwork: function(cb) { 22051 var that = this, settings; 22052 if (!cb) { 22053 return; 22054 } 22055 settings = this.prepare(this._settings()); 22056 this.transport(settings).fail(onError).done(onResponse); 22057 function onError() { 22058 cb(true); 22059 } 22060 function onResponse(resp) { 22061 cb(null, that.transform(resp)); 22062 } 22063 }, 22064 clear: function clear() { 22065 this.storage.clear(); 22066 return this; 22067 } 22068 }); 22069 return Prefetch; 22070 }(); 22071 var Remote = function() { 22072 "use strict"; 22073 function Remote(o) { 22074 this.url = o.url; 22075 this.prepare = o.prepare; 22076 this.transform = o.transform; 22077 this.transport = new Transport({ 22078 cache: o.cache, 22079 limiter: o.limiter, 22080 transport: o.transport 22081 }); 22082 } 22083 _.mixin(Remote.prototype, { 22084 _settings: function settings() { 22085 return { 22086 url: this.url, 22087 type: "GET", 22088 dataType: "json" 22089 }; 22090 }, 22091 get: function get(query, cb) { 22092 var that = this, settings; 22093 if (!cb) { 22094 return; 22095 } 22096 query = query || ""; 22097 settings = this.prepare(query, this._settings()); 22098 return this.transport.get(settings, onResponse); 22099 function onResponse(err, resp) { 22100 err ? cb([]) : cb(that.transform(resp)); 22101 } 22102 }, 22103 cancelLastRequest: function cancelLastRequest() { 22104 this.transport.cancel(); 22105 } 22106 }); 22107 return Remote; 22108 }(); 22109 var oParser = function() { 22110 "use strict"; 22111 return function parse(o) { 22112 var defaults, sorter; 22113 defaults = { 22114 initialize: true, 22115 identify: _.stringify, 22116 datumTokenizer: null, 22117 queryTokenizer: null, 22118 sufficient: 5, 22119 sorter: null, 22120 local: [], 22121 prefetch: null, 22122 remote: null 22123 }; 22124 o = _.mixin(defaults, o || {}); 22125 !o.datumTokenizer && $.error("datumTokenizer is required"); 22126 !o.queryTokenizer && $.error("queryTokenizer is required"); 22127 sorter = o.sorter; 22128 o.sorter = sorter ? function(x) { 22129 return x.sort(sorter); 22130 } : _.identity; 22131 o.local = _.isFunction(o.local) ? o.local() : o.local; 22132 o.prefetch = parsePrefetch(o.prefetch); 22133 o.remote = parseRemote(o.remote); 22134 return o; 22135 }; 22136 function parsePrefetch(o) { 22137 var defaults; 22138 if (!o) { 22139 return null; 22140 } 22141 defaults = { 22142 url: null, 22143 ttl: 24 * 60 * 60 * 1e3, 22144 cache: true, 22145 cacheKey: null, 22146 thumbprint: "", 22147 prepare: _.identity, 22148 transform: _.identity, 22149 transport: null 22150 }; 22151 o = _.isString(o) ? { 22152 url: o 22153 } : o; 22154 o = _.mixin(defaults, o); 22155 !o.url && $.error("prefetch requires url to be set"); 22156 o.transform = o.filter || o.transform; 22157 o.cacheKey = o.cacheKey || o.url; 22158 o.thumbprint = VERSION + o.thumbprint; 22159 o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; 22160 return o; 22161 } 22162 function parseRemote(o) { 22163 var defaults; 22164 if (!o) { 22165 return; 22166 } 22167 defaults = { 22168 url: null, 22169 cache: true, 22170 prepare: null, 22171 replace: null, 22172 wildcard: null, 22173 limiter: null, 22174 rateLimitBy: "debounce", 22175 rateLimitWait: 300, 22176 transform: _.identity, 22177 transport: null 22178 }; 22179 o = _.isString(o) ? { 22180 url: o 22181 } : o; 22182 o = _.mixin(defaults, o); 22183 !o.url && $.error("remote requires url to be set"); 22184 o.transform = o.filter || o.transform; 22185 o.prepare = toRemotePrepare(o); 22186 o.limiter = toLimiter(o); 22187 o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax; 22188 delete o.replace; 22189 delete o.wildcard; 22190 delete o.rateLimitBy; 22191 delete o.rateLimitWait; 22192 return o; 22193 } 22194 function toRemotePrepare(o) { 22195 var prepare, replace, wildcard; 22196 prepare = o.prepare; 22197 replace = o.replace; 22198 wildcard = o.wildcard; 22199 if (prepare) { 22200 return prepare; 22201 } 22202 if (replace) { 22203 prepare = prepareByReplace; 22204 } else if (o.wildcard) { 22205 prepare = prepareByWildcard; 22206 } else { 22207 prepare = idenityPrepare; 22208 } 22209 return prepare; 22210 function prepareByReplace(query, settings) { 22211 settings.url = replace(settings.url, query); 22212 return settings; 22213 } 22214 function prepareByWildcard(query, settings) { 22215 settings.url = settings.url.replace(wildcard, encodeURIComponent(query)); 22216 return settings; 22217 } 22218 function idenityPrepare(query, settings) { 22219 return settings; 22220 } 22221 } 22222 function toLimiter(o) { 22223 var limiter, method, wait; 22224 limiter = o.limiter; 22225 method = o.rateLimitBy; 22226 wait = o.rateLimitWait; 22227 if (!limiter) { 22228 limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait); 22229 } 22230 return limiter; 22231 function debounce(wait) { 22232 return function debounce(fn) { 22233 return _.debounce(fn, wait); 22234 }; 22235 } 22236 function throttle(wait) { 22237 return function throttle(fn) { 22238 return _.throttle(fn, wait); 22239 }; 22240 } 22241 } 22242 function callbackToDeferred(fn) { 22243 return function wrapper(o) { 22244 var deferred = $.Deferred(); 22245 fn(o, onSuccess, onError); 22246 return deferred; 22247 function onSuccess(resp) { 22248 _.defer(function() { 22249 deferred.resolve(resp); 22250 }); 22251 } 22252 function onError(err) { 22253 _.defer(function() { 22254 deferred.reject(err); 22255 }); 22256 } 22257 }; 22258 } 22259 }(); 22260 var Bloodhound = function() { 22261 "use strict"; 22262 var old; 22263 old = window && window.Bloodhound; 22264 function Bloodhound(o) { 22265 o = oParser(o); 22266 this.sorter = o.sorter; 22267 this.identify = o.identify; 22268 this.sufficient = o.sufficient; 22269 this.local = o.local; 22270 this.remote = o.remote ? new Remote(o.remote) : null; 22271 this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null; 22272 this.index = new SearchIndex({ 22273 identify: this.identify, 22274 datumTokenizer: o.datumTokenizer, 22275 queryTokenizer: o.queryTokenizer 22276 }); 22277 o.initialize !== false && this.initialize(); 22278 } 22279 Bloodhound.noConflict = function noConflict() { 22280 window && (window.Bloodhound = old); 22281 return Bloodhound; 22282 }; 22283 Bloodhound.tokenizers = tokenizers; 22284 _.mixin(Bloodhound.prototype, { 22285 __ttAdapter: function ttAdapter() { 22286 var that = this; 22287 return this.remote ? withAsync : withoutAsync; 22288 function withAsync(query, sync, async) { 22289 return that.search(query, sync, async); 22290 } 22291 function withoutAsync(query, sync) { 22292 return that.search(query, sync); 22293 } 22294 }, 22295 _loadPrefetch: function loadPrefetch() { 22296 var that = this, deferred, serialized; 22297 deferred = $.Deferred(); 22298 if (!this.prefetch) { 22299 deferred.resolve(); 22300 } else if (serialized = this.prefetch.fromCache()) { 22301 this.index.bootstrap(serialized); 22302 deferred.resolve(); 22303 } else { 22304 this.prefetch.fromNetwork(done); 22305 } 22306 return deferred.promise(); 22307 function done(err, data) { 22308 if (err) { 22309 return deferred.reject(); 22310 } 22311 that.add(data); 22312 that.prefetch.store(that.index.serialize()); 22313 deferred.resolve(); 22314 } 22315 }, 22316 _initialize: function initialize() { 22317 var that = this, deferred; 22318 this.clear(); 22319 (this.initPromise = this._loadPrefetch()).done(addLocalToIndex); 22320 return this.initPromise; 22321 function addLocalToIndex() { 22322 that.add(that.local); 22323 } 22324 }, 22325 initialize: function initialize(force) { 22326 return !this.initPromise || force ? this._initialize() : this.initPromise; 22327 }, 22328 add: function add(data) { 22329 this.index.add(data); 22330 return this; 22331 }, 22332 get: function get(ids) { 22333 ids = _.isArray(ids) ? ids : [].slice.call(arguments); 22334 return this.index.get(ids); 22335 }, 22336 search: function search(query, sync, async) { 22337 var that = this, local; 22338 local = this.sorter(this.index.search(query)); 22339 sync(this.remote ? local.slice() : local); 22340 if (this.remote && local.length < this.sufficient) { 22341 this.remote.get(query, processRemote); 22342 } else if (this.remote) { 22343 this.remote.cancelLastRequest(); 22344 } 22345 return this; 22346 function processRemote(remote) {
vendor: 3,453 bytes, lines 22347-22446
22347 var nonDuplicates = []; 22348 _.each(remote, function(r) { 22349 !_.some(local, function(l) { 22350 return that.identify(r) === that.identify(l); 22351 }) && nonDuplicates.push(r); 22352 }); 22353 async && async(nonDuplicates); 22354 } 22355 }, 22356 all: function all() { 22357 return this.index.all(); 22358 }, 22359 clear: function clear() { 22360 this.index.reset(); 22361 return this; 22362 }, 22363 clearPrefetchCache: function clearPrefetchCache() { 22364 this.prefetch && this.prefetch.clear(); 22365 return this; 22366 }, 22367 clearRemoteCache: function clearRemoteCache() { 22368 Transport.resetCache(); 22369 return this; 22370 }, 22371 ttAdapter: function ttAdapter() { 22372 return this.__ttAdapter(); 22373 } 22374 }); 22375 return Bloodhound; 22376 }(); 22377 return Bloodhound; 22378}); 22379 22380(function(root, factory) { 22381 if (typeof define === "function" && define.amd) { 22382 define("typeahead.js", [ "jquery" ], function(a0) { 22383 return factory(a0); 22384 }); 22385 } else if (typeof exports === "object") { 22386 module.exports = factory(require("jquery")); 22387 } else { 22388 factory(jQuery); 22389 } 22390})(this, function($) { 22391 var _ = function() { 22392 "use strict"; 22393 return { 22394 isMsie: function() { 22395 return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false; 22396 }, 22397 isBlankString: function(str) { 22398 return !str || /^\s*$/.test(str); 22399 }, 22400 escapeRegExChars: function(str) { 22401 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 22402 }, 22403 isString: function(obj) { 22404 return typeof obj === "string"; 22405 }, 22406 isNumber: function(obj) { 22407 return typeof obj === "number"; 22408 }, 22409 isArray: $.isArray, 22410 isFunction: $.isFunction, 22411 isObject: $.isPlainObject, 22412 isUndefined: function(obj) { 22413 return typeof obj === "undefined"; 22414 }, 22415 isElement: function(obj) { 22416 return !!(obj && obj.nodeType === 1); 22417 }, 22418 isJQuery: function(obj) { 22419 return obj instanceof $; 22420 }, 22421 toStr: function toStr(s) { 22422 return _.isUndefined(s) || s === null ? "" : s + ""; 22423 }, 22424 bind: $.proxy, 22425 each: function(collection, cb) { 22426 $.each(collection, reverseArgs); 22427 function reverseArgs(index, value) { 22428 return cb(value, index); 22429 } 22430 }, 22431 map: $.map, 22432 filter: $.grep, 22433 every: function(obj, test) { 22434 var result = true; 22435 if (!obj) { 22436 return result; 22437 } 22438 $.each(obj, function(key, val) { 22439 if (!(result = test.call(null, val, key, obj))) { 22440 return false; 22441 } 22442 }); 22443 return !!result; 22444 }, 22445 some: function(obj, test) { 22446 var result = false;
vendor: 60,610 bytes, lines 22447-23911
22447 if (!obj) { 22448 return result; 22449 } 22450 $.each(obj, function(key, val) { 22451 if (result = test.call(null, val, key, obj)) { 22452 return false; 22453 } 22454 }); 22455 return !!result; 22456 }, 22457 mixin: $.extend, 22458 identity: function(x) { 22459 return x; 22460 }, 22461 clone: function(obj) { 22462 return $.extend(true, {}, obj); 22463 }, 22464 getIdGenerator: function() { 22465 var counter = 0; 22466 return function() { 22467 return counter++; 22468 }; 22469 }, 22470 templatify: function templatify(obj) { 22471 return $.isFunction(obj) ? obj : template; 22472 function template() { 22473 return String(obj); 22474 } 22475 }, 22476 defer: function(fn) { 22477 setTimeout(fn, 0); 22478 }, 22479 debounce: function(func, wait, immediate) { 22480 var timeout, result; 22481 return function() { 22482 var context = this, args = arguments, later, callNow; 22483 later = function() { 22484 timeout = null; 22485 if (!immediate) { 22486 result = func.apply(context, args); 22487 } 22488 }; 22489 callNow = immediate && !timeout; 22490 clearTimeout(timeout); 22491 timeout = setTimeout(later, wait); 22492 if (callNow) { 22493 result = func.apply(context, args); 22494 } 22495 return result; 22496 }; 22497 }, 22498 throttle: function(func, wait) { 22499 var context, args, timeout, result, previous, later; 22500 previous = 0; 22501 later = function() { 22502 previous = new Date(); 22503 timeout = null; 22504 result = func.apply(context, args); 22505 }; 22506 return function() { 22507 var now = new Date(), remaining = wait - (now - previous); 22508 context = this; 22509 args = arguments; 22510 if (remaining <= 0) { 22511 clearTimeout(timeout); 22512 timeout = null; 22513 previous = now; 22514 result = func.apply(context, args); 22515 } else if (!timeout) { 22516 timeout = setTimeout(later, remaining); 22517 } 22518 return result; 22519 }; 22520 }, 22521 stringify: function(val) { 22522 return _.isString(val) ? val : JSON.stringify(val); 22523 }, 22524 noop: function() {} 22525 }; 22526 }(); 22527 var WWW = function() { 22528 "use strict"; 22529 var defaultClassNames = { 22530 wrapper: "twitter-typeahead", 22531 input: "tt-input", 22532 hint: "tt-hint", 22533 menu: "tt-menu", 22534 dataset: "tt-dataset", 22535 suggestion: "tt-suggestion", 22536 selectable: "tt-selectable", 22537 empty: "tt-empty", 22538 open: "tt-open", 22539 cursor: "tt-cursor", 22540 highlight: "tt-highlight" 22541 }; 22542 return build; 22543 function build(o) { 22544 var www, classes; 22545 classes = _.mixin({}, defaultClassNames, o); 22546 www = { 22547 css: buildCss(), 22548 classes: classes, 22549 html: buildHtml(classes), 22550 selectors: buildSelectors(classes) 22551 }; 22552 return { 22553 css: www.css, 22554 html: www.html, 22555 classes: www.classes, 22556 selectors: www.selectors, 22557 mixin: function(o) { 22558 _.mixin(o, www); 22559 } 22560 }; 22561 } 22562 function buildHtml(c) { 22563 return { 22564 wrapper: '<span class="' + c.wrapper + '"></span>', 22565 menu: '<div class="' + c.menu + '"></div>' 22566 }; 22567 } 22568 function buildSelectors(classes) { 22569 var selectors = {}; 22570 _.each(classes, function(v, k) { 22571 selectors[k] = "." + v; 22572 }); 22573 return selectors; 22574 } 22575 function buildCss() { 22576 var css = { 22577 wrapper: { 22578 position: "relative", 22579 display: "inline-block" 22580 }, 22581 hint: { 22582 position: "absolute", 22583 top: "0", 22584 left: "0", 22585 borderColor: "transparent", 22586 boxShadow: "none", 22587 opacity: "1" 22588 }, 22589 input: { 22590 position: "relative", 22591 verticalAlign: "top", 22592 backgroundColor: "transparent" 22593 }, 22594 inputWithNoHint: { 22595 position: "relative", 22596 verticalAlign: "top" 22597 }, 22598 menu: { 22599 position: "absolute", 22600 top: "100%", 22601 left: "0", 22602 zIndex: "100", 22603 display: "none" 22604 }, 22605 ltr: { 22606 left: "0", 22607 right: "auto" 22608 }, 22609 rtl: { 22610 left: "auto", 22611 right: " 0" 22612 } 22613 }; 22614 if (_.isMsie()) { 22615 _.mixin(css.input, { 22616 backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" 22617 }); 22618 } 22619 return css; 22620 } 22621 }(); 22622 var EventBus = function() { 22623 "use strict"; 22624 var namespace, deprecationMap; 22625 namespace = "typeahead:"; 22626 deprecationMap = { 22627 render: "rendered", 22628 cursorchange: "cursorchanged", 22629 select: "selected", 22630 autocomplete: "autocompleted" 22631 }; 22632 function EventBus(o) { 22633 if (!o || !o.el) { 22634 $.error("EventBus initialized without el"); 22635 } 22636 this.$el = $(o.el); 22637 } 22638 _.mixin(EventBus.prototype, { 22639 _trigger: function(type, args) { 22640 var $e; 22641 $e = $.Event(namespace + type); 22642 (args = args || []).unshift($e); 22643 this.$el.trigger.apply(this.$el, args); 22644 return $e; 22645 }, 22646 before: function(type) { 22647 var args, $e; 22648 args = [].slice.call(arguments, 1); 22649 $e = this._trigger("before" + type, args); 22650 return $e.isDefaultPrevented(); 22651 }, 22652 trigger: function(type) { 22653 var deprecatedType; 22654 this._trigger(type, [].slice.call(arguments, 1)); 22655 if (deprecatedType = deprecationMap[type]) { 22656 this._trigger(deprecatedType, [].slice.call(arguments, 1)); 22657 } 22658 } 22659 }); 22660 return EventBus; 22661 }(); 22662 var EventEmitter = function() { 22663 "use strict"; 22664 var splitter = /\s+/, nextTick = getNextTick(); 22665 return { 22666 onSync: onSync, 22667 onAsync: onAsync, 22668 off: off, 22669 trigger: trigger 22670 }; 22671 function on(method, types, cb, context) { 22672 var type; 22673 if (!cb) { 22674 return this; 22675 } 22676 types = types.split(splitter); 22677 cb = context ? bindContext(cb, context) : cb; 22678 this._callbacks = this._callbacks || {}; 22679 while (type = types.shift()) { 22680 this._callbacks[type] = this._callbacks[type] || { 22681 sync: [], 22682 async: [] 22683 }; 22684 this._callbacks[type][method].push(cb); 22685 } 22686 return this; 22687 } 22688 function onAsync(types, cb, context) { 22689 return on.call(this, "async", types, cb, context); 22690 } 22691 function onSync(types, cb, context) { 22692 return on.call(this, "sync", types, cb, context); 22693 } 22694 function off(types) { 22695 var type; 22696 if (!this._callbacks) { 22697 return this; 22698 } 22699 types = types.split(splitter); 22700 while (type = types.shift()) { 22701 delete this._callbacks[type]; 22702 } 22703 return this; 22704 } 22705 function trigger(types) { 22706 var type, callbacks, args, syncFlush, asyncFlush; 22707 if (!this._callbacks) { 22708 return this; 22709 } 22710 types = types.split(splitter); 22711 args = [].slice.call(arguments, 1); 22712 while ((type = types.shift()) && (callbacks = this._callbacks[type])) { 22713 syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args)); 22714 asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args)); 22715 syncFlush() && nextTick(asyncFlush); 22716 } 22717 return this; 22718 } 22719 function getFlush(callbacks, context, args) { 22720 return flush; 22721 function flush() { 22722 var cancelled; 22723 for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) { 22724 cancelled = callbacks[i].apply(context, args) === false; 22725 } 22726 return !cancelled; 22727 } 22728 } 22729 function getNextTick() { 22730 var nextTickFn; 22731 if (window.setImmediate) { 22732 nextTickFn = function nextTickSetImmediate(fn) { 22733 setImmediate(function() { 22734 fn(); 22735 }); 22736 }; 22737 } else { 22738 nextTickFn = function nextTickSetTimeout(fn) { 22739 setTimeout(function() { 22740 fn(); 22741 }, 0); 22742 }; 22743 } 22744 return nextTickFn; 22745 } 22746 function bindContext(fn, context) { 22747 return fn.bind ? fn.bind(context) : function() { 22748 fn.apply(context, [].slice.call(arguments, 0)); 22749 }; 22750 } 22751 }(); 22752 var highlight = function(doc) { 22753 "use strict"; 22754 var defaults = { 22755 node: null, 22756 pattern: null, 22757 tagName: "strong", 22758 className: null, 22759 wordsOnly: false, 22760 caseSensitive: false 22761 }; 22762 return function hightlight(o) { 22763 var regex; 22764 o = _.mixin({}, defaults, o); 22765 if (!o.node || !o.pattern) { 22766 return; 22767 } 22768 o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ]; 22769 regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly); 22770 traverse(o.node, hightlightTextNode); 22771 function hightlightTextNode(textNode) { 22772 var match, patternNode, wrapperNode; 22773 if (match = regex.exec(textNode.data)) { 22774 wrapperNode = doc.createElement(o.tagName); 22775 o.className && (wrapperNode.className = o.className); 22776 patternNode = textNode.splitText(match.index); 22777 patternNode.splitText(match[0].length); 22778 wrapperNode.appendChild(patternNode.cloneNode(true)); 22779 textNode.parentNode.replaceChild(wrapperNode, patternNode); 22780 } 22781 return !!match; 22782 } 22783 function traverse(el, hightlightTextNode) { 22784 var childNode, TEXT_NODE_TYPE = 3; 22785 for (var i = 0; i < el.childNodes.length; i++) { 22786 childNode = el.childNodes[i]; 22787 if (childNode.nodeType === TEXT_NODE_TYPE) { 22788 i += hightlightTextNode(childNode) ? 1 : 0; 22789 } else { 22790 traverse(childNode, hightlightTextNode); 22791 } 22792 } 22793 } 22794 }; 22795 function getRegex(patterns, caseSensitive, wordsOnly) { 22796 var escapedPatterns = [], regexStr; 22797 for (var i = 0, len = patterns.length; i < len; i++) { 22798 escapedPatterns.push(_.escapeRegExChars(patterns[i])); 22799 } 22800 regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")"; 22801 return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i"); 22802 } 22803 }(window.document); 22804 var Input = function() { 22805 "use strict"; 22806 var specialKeyCodeMap; 22807 specialKeyCodeMap = { 22808 9: "tab", 22809 27: "esc", 22810 37: "left", 22811 39: "right", 22812 13: "enter", 22813 38: "up", 22814 40: "down" 22815 }; 22816 function Input(o, www) { 22817 o = o || {}; 22818 if (!o.input) { 22819 $.error("input is missing"); 22820 } 22821 www.mixin(this); 22822 this.$hint = $(o.hint); 22823 this.$input = $(o.input); 22824 this.query = this.$input.val(); 22825 this.queryWhenFocused = this.hasFocus() ? this.query : null; 22826 this.$overflowHelper = buildOverflowHelper(this.$input); 22827 this._checkLanguageDirection(); 22828 if (this.$hint.length === 0) { 22829 this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop; 22830 } 22831 } 22832 Input.normalizeQuery = function(str) { 22833 return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " "); 22834 }; 22835 _.mixin(Input.prototype, EventEmitter, { 22836 _onBlur: function onBlur() { 22837 this.resetInputValue(); 22838 this.trigger("blurred"); 22839 }, 22840 _onFocus: function onFocus() { 22841 this.queryWhenFocused = this.query; 22842 this.trigger("focused"); 22843 }, 22844 _onKeydown: function onKeydown($e) { 22845 var keyName = specialKeyCodeMap[$e.which || $e.keyCode]; 22846 this._managePreventDefault(keyName, $e); 22847 if (keyName && this._shouldTrigger(keyName, $e)) { 22848 this.trigger(keyName + "Keyed", $e); 22849 } 22850 }, 22851 _onInput: function onInput() { 22852 this._setQuery(this.getInputValue()); 22853 this.clearHintIfInvalid(); 22854 this._checkLanguageDirection(); 22855 }, 22856 _managePreventDefault: function managePreventDefault(keyName, $e) { 22857 var preventDefault; 22858 switch (keyName) { 22859 case "up": 22860 case "down": 22861 preventDefault = !withModifier($e); 22862 break; 22863 22864 default: 22865 preventDefault = false; 22866 } 22867 preventDefault && $e.preventDefault(); 22868 }, 22869 _shouldTrigger: function shouldTrigger(keyName, $e) { 22870 var trigger; 22871 switch (keyName) { 22872 case "tab": 22873 trigger = !withModifier($e); 22874 break; 22875 22876 default: 22877 trigger = true; 22878 } 22879 return trigger; 22880 }, 22881 _checkLanguageDirection: function checkLanguageDirection() { 22882 var dir = (this.$input.css("direction") || "ltr").toLowerCase(); 22883 if (this.dir !== dir) { 22884 this.dir = dir; 22885 this.$hint.attr("dir", dir); 22886 this.trigger("langDirChanged", dir); 22887 } 22888 }, 22889 _setQuery: function setQuery(val, silent) { 22890 var areEquivalent, hasDifferentWhitespace; 22891 areEquivalent = areQueriesEquivalent(val, this.query); 22892 hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false; 22893 this.query = val; 22894 if (!silent && !areEquivalent) { 22895 this.trigger("queryChanged", this.query); 22896 } else if (!silent && hasDifferentWhitespace) { 22897 this.trigger("whitespaceChanged", this.query); 22898 } 22899 }, 22900 bind: function() { 22901 var that = this, onBlur, onFocus, onKeydown, onInput; 22902 onBlur = _.bind(this._onBlur, this); 22903 onFocus = _.bind(this._onFocus, this); 22904 onKeydown = _.bind(this._onKeydown, this); 22905 onInput = _.bind(this._onInput, this); 22906 this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown); 22907 if (!_.isMsie() || _.isMsie() > 9) { 22908 this.$input.on("input.tt", onInput); 22909 } else { 22910 this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { 22911 if (specialKeyCodeMap[$e.which || $e.keyCode]) { 22912 return; 22913 } 22914 _.defer(_.bind(that._onInput, that, $e)); 22915 }); 22916 } 22917 return this; 22918 }, 22919 focus: function focus() { 22920 this.$input.focus(); 22921 }, 22922 blur: function blur() { 22923 this.$input.blur(); 22924 }, 22925 getLangDir: function getLangDir() { 22926 return this.dir; 22927 }, 22928 getQuery: function getQuery() { 22929 return this.query || ""; 22930 }, 22931 setQuery: function setQuery(val, silent) { 22932 this.setInputValue(val); 22933 this._setQuery(val, silent); 22934 }, 22935 hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() { 22936 return this.query !== this.queryWhenFocused; 22937 }, 22938 getInputValue: function getInputValue() { 22939 return this.$input.val(); 22940 }, 22941 setInputValue: function setInputValue(value) { 22942 this.$input.val(value); 22943 this.clearHintIfInvalid(); 22944 this._checkLanguageDirection(); 22945 }, 22946 resetInputValue: function resetInputValue() { 22947 this.setInputValue(this.query); 22948 }, 22949 getHint: function getHint() { 22950 return this.$hint.val(); 22951 }, 22952 setHint: function setHint(value) { 22953 this.$hint.val(value); 22954 }, 22955 clearHint: function clearHint() { 22956 this.setHint(""); 22957 }, 22958 clearHintIfInvalid: function clearHintIfInvalid() { 22959 var val, hint, valIsPrefixOfHint, isValid; 22960 val = this.getInputValue(); 22961 hint = this.getHint(); 22962 valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0; 22963 isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow(); 22964 !isValid && this.clearHint(); 22965 }, 22966 hasFocus: function hasFocus() { 22967 return this.$input.is(":focus"); 22968 }, 22969 hasOverflow: function hasOverflow() { 22970 var constraint = this.$input.width() - 2; 22971 this.$overflowHelper.text(this.getInputValue()); 22972 return this.$overflowHelper.width() >= constraint; 22973 }, 22974 isCursorAtEnd: function() { 22975 var valueLength, selectionStart, range; 22976 valueLength = this.$input.val().length; 22977 selectionStart = this.$input[0].selectionStart; 22978 if (_.isNumber(selectionStart)) { 22979 return selectionStart === valueLength; 22980 } else if (document.selection) { 22981 range = document.selection.createRange(); 22982 range.moveStart("character", -valueLength); 22983 return valueLength === range.text.length; 22984 } 22985 return true; 22986 }, 22987 destroy: function destroy() { 22988 this.$hint.off(".tt"); 22989 this.$input.off(".tt"); 22990 this.$overflowHelper.remove(); 22991 this.$hint = this.$input = this.$overflowHelper = $("<div>"); 22992 } 22993 }); 22994 return Input; 22995 function buildOverflowHelper($input) { 22996 return $('<pre aria-hidden="true"></pre>').css({ 22997 position: "absolute", 22998 visibility: "hidden", 22999 whiteSpace: "pre", 23000 fontFamily: $input.css("font-family"), 23001 fontSize: $input.css("font-size"), 23002 fontStyle: $input.css("font-style"), 23003 fontVariant: $input.css("font-variant"), 23004 fontWeight: $input.css("font-weight"), 23005 wordSpacing: $input.css("word-spacing"), 23006 letterSpacing: $input.css("letter-spacing"), 23007 textIndent: $input.css("text-indent"), 23008 textRendering: $input.css("text-rendering"), 23009 textTransform: $input.css("text-transform") 23010 }).insertAfter($input); 23011 } 23012 function areQueriesEquivalent(a, b) { 23013 return Input.normalizeQuery(a) === Input.normalizeQuery(b); 23014 } 23015 function withModifier($e) { 23016 return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey; 23017 } 23018 }(); 23019 var Dataset = function() { 23020 "use strict"; 23021 var keys, nameGenerator; 23022 keys = { 23023 val: "tt-selectable-display", 23024 obj: "tt-selectable-object" 23025 }; 23026 nameGenerator = _.getIdGenerator(); 23027 function Dataset(o, www) { 23028 o = o || {}; 23029 o.templates = o.templates || {}; 23030 o.templates.notFound = o.templates.notFound || o.templates.empty; 23031 if (!o.source) { 23032 $.error("missing source"); 23033 } 23034 if (!o.node) { 23035 $.error("missing node"); 23036 } 23037 if (o.name && !isValidName(o.name)) { 23038 $.error("invalid dataset name: " + o.name); 23039 } 23040 www.mixin(this); 23041 this.highlight = !!o.highlight; 23042 this.name = o.name || nameGenerator(); 23043 this.limit = o.limit || 5; 23044 this.displayFn = getDisplayFn(o.display || o.displayKey); 23045 this.templates = getTemplates(o.templates, this.displayFn); 23046 this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source; 23047 this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async; 23048 this._resetLastSuggestion(); 23049 this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name); 23050 } 23051 Dataset.extractData = function extractData(el) { 23052 var $el = $(el); 23053 if ($el.data(keys.obj)) { 23054 return { 23055 val: $el.data(keys.val) || "", 23056 obj: $el.data(keys.obj) || null 23057 }; 23058 } 23059 return null; 23060 }; 23061 _.mixin(Dataset.prototype, EventEmitter, { 23062 _overwrite: function overwrite(query, suggestions) { 23063 suggestions = suggestions || []; 23064 if (suggestions.length) { 23065 this._renderSuggestions(query, suggestions); 23066 } else if (this.async && this.templates.pending) { 23067 this._renderPending(query); 23068 } else if (!this.async && this.templates.notFound) { 23069 this._renderNotFound(query); 23070 } else { 23071 this._empty(); 23072 } 23073 this.trigger("rendered", this.name, suggestions, false); 23074 }, 23075 _append: function append(query, suggestions) { 23076 suggestions = suggestions || []; 23077 if (suggestions.length && this.$lastSuggestion.length) { 23078 this._appendSuggestions(query, suggestions); 23079 } else if (suggestions.length) { 23080 this._renderSuggestions(query, suggestions); 23081 } else if (!this.$lastSuggestion.length && this.templates.notFound) { 23082 this._renderNotFound(query); 23083 } 23084 this.trigger("rendered", this.name, suggestions, true); 23085 }, 23086 _renderSuggestions: function renderSuggestions(query, suggestions) { 23087 var $fragment; 23088 $fragment = this._getSuggestionsFragment(query, suggestions); 23089 this.$lastSuggestion = $fragment.children().last(); 23090 this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions)); 23091 }, 23092 _appendSuggestions: function appendSuggestions(query, suggestions) { 23093 var $fragment, $lastSuggestion; 23094 $fragment = this._getSuggestionsFragment(query, suggestions); 23095 $lastSuggestion = $fragment.children().last(); 23096 this.$lastSuggestion.after($fragment); 23097 this.$lastSuggestion = $lastSuggestion; 23098 }, 23099 _renderPending: function renderPending(query) { 23100 var template = this.templates.pending; 23101 this._resetLastSuggestion(); 23102 template && this.$el.html(template({ 23103 query: query, 23104 dataset: this.name 23105 })); 23106 }, 23107 _renderNotFound: function renderNotFound(query) { 23108 var template = this.templates.notFound; 23109 this._resetLastSuggestion(); 23110 template && this.$el.html(template({ 23111 query: query, 23112 dataset: this.name 23113 })); 23114 }, 23115 _empty: function empty() { 23116 this.$el.empty(); 23117 this._resetLastSuggestion(); 23118 }, 23119 _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) { 23120 var that = this, fragment; 23121 fragment = document.createDocumentFragment(); 23122 _.each(suggestions, function getSuggestionNode(suggestion) { 23123 var $el, context; 23124 context = that._injectQuery(query, suggestion); 23125 $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable); 23126 fragment.appendChild($el[0]); 23127 }); 23128 this.highlight && highlight({ 23129 className: this.classes.highlight, 23130 node: fragment, 23131 pattern: query 23132 }); 23133 return $(fragment); 23134 }, 23135 _getFooter: function getFooter(query, suggestions) { 23136 return this.templates.footer ? this.templates.footer({ 23137 query: query, 23138 suggestions: suggestions, 23139 dataset: this.name 23140 }) : null; 23141 }, 23142 _getHeader: function getHeader(query, suggestions) { 23143 return this.templates.header ? this.templates.header({ 23144 query: query, 23145 suggestions: suggestions, 23146 dataset: this.name 23147 }) : null; 23148 }, 23149 _resetLastSuggestion: function resetLastSuggestion() { 23150 this.$lastSuggestion = $(); 23151 }, 23152 _injectQuery: function injectQuery(query, obj) { 23153 return _.isObject(obj) ? _.mixin({ 23154 _query: query 23155 }, obj) : obj; 23156 }, 23157 update: function update(query) { 23158 var that = this, canceled = false, syncCalled = false, rendered = 0; 23159 this.cancel(); 23160 this.cancel = function cancel() { 23161 canceled = true; 23162 that.cancel = $.noop; 23163 that.async && that.trigger("asyncCanceled", query); 23164 }; 23165 this.source(query, sync, async); 23166 !syncCalled && sync([]); 23167 function sync(suggestions) { 23168 if (syncCalled) { 23169 return; 23170 } 23171 syncCalled = true; 23172 suggestions = (suggestions || []).slice(0, that.limit); 23173 rendered = suggestions.length; 23174 that._overwrite(query, suggestions); 23175 if (rendered < that.limit && that.async) { 23176 that.trigger("asyncRequested", query); 23177 } 23178 } 23179 function async(suggestions) { 23180 suggestions = suggestions || []; 23181 if (!canceled && rendered < that.limit) { 23182 that.cancel = $.noop; 23183 rendered += suggestions.length; 23184 that._append(query, suggestions.slice(0, that.limit - rendered)); 23185 that.async && that.trigger("asyncReceived", query); 23186 } 23187 } 23188 }, 23189 cancel: $.noop, 23190 clear: function clear() { 23191 this._empty(); 23192 this.cancel(); 23193 this.trigger("cleared"); 23194 }, 23195 isEmpty: function isEmpty() { 23196 return this.$el.is(":empty"); 23197 }, 23198 destroy: function destroy() { 23199 this.$el = $("<div>"); 23200 } 23201 }); 23202 return Dataset; 23203 function getDisplayFn(display) { 23204 display = display || _.stringify; 23205 return _.isFunction(display) ? display : displayFn; 23206 function displayFn(obj) { 23207 return obj[display]; 23208 } 23209 } 23210 function getTemplates(templates, displayFn) { 23211 return { 23212 notFound: templates.notFound && _.templatify(templates.notFound), 23213 pending: templates.pending && _.templatify(templates.pending), 23214 header: templates.header && _.templatify(templates.header), 23215 footer: templates.footer && _.templatify(templates.footer), 23216 suggestion: templates.suggestion || suggestionTemplate 23217 }; 23218 function suggestionTemplate(context) { 23219 return $("<div>").text(displayFn(context)); 23220 } 23221 } 23222 function isValidName(str) { 23223 return /^[_a-zA-Z0-9-]+$/.test(str); 23224 } 23225 }(); 23226 var Menu = function() { 23227 "use strict"; 23228 function Menu(o, www) { 23229 var that = this; 23230 o = o || {}; 23231 if (!o.node) { 23232 $.error("node is required"); 23233 } 23234 www.mixin(this); 23235 this.$node = $(o.node); 23236 this.query = null; 23237 this.datasets = _.map(o.datasets, initializeDataset); 23238 function initializeDataset(oDataset) { 23239 var node = that.$node.find(oDataset.node).first(); 23240 oDataset.node = node.length ? node : $("<div>").appendTo(that.$node); 23241 return new Dataset(oDataset, www); 23242 } 23243 } 23244 _.mixin(Menu.prototype, EventEmitter, { 23245 _onSelectableClick: function onSelectableClick($e) { 23246 this.trigger("selectableClicked", $($e.currentTarget)); 23247 }, 23248 _onRendered: function onRendered(type, dataset, suggestions, async) { 23249 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 23250 this.trigger("datasetRendered", dataset, suggestions, async); 23251 }, 23252 _onCleared: function onCleared() { 23253 this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty()); 23254 this.trigger("datasetCleared"); 23255 }, 23256 _propagate: function propagate() { 23257 this.trigger.apply(this, arguments); 23258 }, 23259 _allDatasetsEmpty: function allDatasetsEmpty() { 23260 return _.every(this.datasets, isDatasetEmpty); 23261 function isDatasetEmpty(dataset) { 23262 return dataset.isEmpty(); 23263 } 23264 }, 23265 _getSelectables: function getSelectables() { 23266 return this.$node.find(this.selectors.selectable); 23267 }, 23268 _removeCursor: function _removeCursor() { 23269 var $selectable = this.getActiveSelectable(); 23270 $selectable && $selectable.removeClass(this.classes.cursor); 23271 }, 23272 _ensureVisible: function ensureVisible($el) { 23273 var elTop, elBottom, nodeScrollTop, nodeHeight; 23274 elTop = $el.position().top; 23275 elBottom = elTop + $el.outerHeight(true); 23276 nodeScrollTop = this.$node.scrollTop(); 23277 nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10); 23278 if (elTop < 0) { 23279 this.$node.scrollTop(nodeScrollTop + elTop); 23280 } else if (nodeHeight < elBottom) { 23281 this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight)); 23282 } 23283 }, 23284 bind: function() { 23285 var that = this, onSelectableClick; 23286 onSelectableClick = _.bind(this._onSelectableClick, this); 23287 this.$node.on("click.tt", this.selectors.selectable, onSelectableClick); 23288 _.each(this.datasets, function(dataset) { 23289 dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that); 23290 }); 23291 return this; 23292 }, 23293 isOpen: function isOpen() { 23294 return this.$node.hasClass(this.classes.open); 23295 }, 23296 open: function open() { 23297 this.$node.addClass(this.classes.open); 23298 }, 23299 close: function close() { 23300 this.$node.removeClass(this.classes.open); 23301 this._removeCursor(); 23302 }, 23303 setLanguageDirection: function setLanguageDirection(dir) { 23304 this.$node.attr("dir", dir); 23305 }, 23306 selectableRelativeToCursor: function selectableRelativeToCursor(delta) { 23307 var $selectables, $oldCursor, oldIndex, newIndex; 23308 $oldCursor = this.getActiveSelectable(); 23309 $selectables = this._getSelectables(); 23310 oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1; 23311 newIndex = oldIndex + delta; 23312 newIndex = (newIndex + 1) % ($selectables.length + 1) - 1; 23313 newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex; 23314 return newIndex === -1 ? null : $selectables.eq(newIndex); 23315 }, 23316 setCursor: function setCursor($selectable) { 23317 this._removeCursor(); 23318 if ($selectable = $selectable && $selectable.first()) { 23319 $selectable.addClass(this.classes.cursor); 23320 this._ensureVisible($selectable); 23321 } 23322 }, 23323 getSelectableData: function getSelectableData($el) { 23324 return $el && $el.length ? Dataset.extractData($el) : null; 23325 }, 23326 getActiveSelectable: function getActiveSelectable() { 23327 var $selectable = this._getSelectables().filter(this.selectors.cursor).first(); 23328 return $selectable.length ? $selectable : null; 23329 }, 23330 getTopSelectable: function getTopSelectable() { 23331 var $selectable = this._getSelectables().first(); 23332 return $selectable.length ? $selectable : null; 23333 }, 23334 update: function update(query) { 23335 var isValidUpdate = query !== this.query; 23336 if (isValidUpdate) { 23337 this.query = query; 23338 _.each(this.datasets, updateDataset); 23339 } 23340 return isValidUpdate; 23341 function updateDataset(dataset) { 23342 dataset.update(query); 23343 } 23344 }, 23345 empty: function empty() { 23346 _.each(this.datasets, clearDataset); 23347 this.query = null; 23348 this.$node.addClass(this.classes.empty); 23349 function clearDataset(dataset) { 23350 dataset.clear(); 23351 } 23352 }, 23353 destroy: function destroy() { 23354 this.$node.off(".tt"); 23355 this.$node = $("<div>"); 23356 _.each(this.datasets, destroyDataset); 23357 function destroyDataset(dataset) { 23358 dataset.destroy(); 23359 } 23360 } 23361 }); 23362 return Menu; 23363 }(); 23364 var DefaultMenu = function() { 23365 "use strict"; 23366 var s = Menu.prototype; 23367 function DefaultMenu() { 23368 Menu.apply(this, [].slice.call(arguments, 0)); 23369 } 23370 _.mixin(DefaultMenu.prototype, Menu.prototype, { 23371 open: function open() { 23372 !this._allDatasetsEmpty() && this._show(); 23373 return s.open.apply(this, [].slice.call(arguments, 0)); 23374 }, 23375 close: function close() { 23376 this._hide(); 23377 return s.close.apply(this, [].slice.call(arguments, 0)); 23378 }, 23379 _onRendered: function onRendered() { 23380 if (this._allDatasetsEmpty()) { 23381 this._hide(); 23382 } else { 23383 this.isOpen() && this._show(); 23384 } 23385 return s._onRendered.apply(this, [].slice.call(arguments, 0)); 23386 }, 23387 _onCleared: function onCleared() { 23388 if (this._allDatasetsEmpty()) { 23389 this._hide(); 23390 } else { 23391 this.isOpen() && this._show(); 23392 } 23393 return s._onCleared.apply(this, [].slice.call(arguments, 0)); 23394 }, 23395 setLanguageDirection: function setLanguageDirection(dir) { 23396 this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl); 23397 return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0)); 23398 }, 23399 _hide: function hide() { 23400 this.$node.hide(); 23401 }, 23402 _show: function show() { 23403 this.$node.css("display", "block"); 23404 } 23405 }); 23406 return DefaultMenu; 23407 }(); 23408 var Typeahead = function() { 23409 "use strict"; 23410 function Typeahead(o, www) { 23411 var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged; 23412 o = o || {}; 23413 if (!o.input) { 23414 $.error("missing input"); 23415 } 23416 if (!o.menu) { 23417 $.error("missing menu"); 23418 } 23419 if (!o.eventBus) { 23420 $.error("missing event bus"); 23421 } 23422 www.mixin(this); 23423 this.eventBus = o.eventBus; 23424 this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; 23425 this.input = o.input; 23426 this.menu = o.menu; 23427 this.enabled = true; 23428 this.active = false; 23429 this.input.hasFocus() && this.activate(); 23430 this.dir = this.input.getLangDir(); 23431 this._hacks(); 23432 this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this); 23433 onFocused = c(this, "activate", "open", "_onFocused"); 23434 onBlurred = c(this, "deactivate", "_onBlurred"); 23435 onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed"); 23436 onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed"); 23437 onEscKeyed = c(this, "isActive", "_onEscKeyed"); 23438 onUpKeyed = c(this, "isActive", "open", "_onUpKeyed"); 23439 onDownKeyed = c(this, "isActive", "open", "_onDownKeyed"); 23440 onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed"); 23441 onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed"); 23442 onQueryChanged = c(this, "_openIfActive", "_onQueryChanged"); 23443 onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged"); 23444 this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this); 23445 } 23446 _.mixin(Typeahead.prototype, { 23447 _hacks: function hacks() { 23448 var $input, $menu; 23449 $input = this.input.$input || $("<div>"); 23450 $menu = this.menu.$node || $("<div>"); 23451 $input.on("blur.tt", function($e) { 23452 var active, isActive, hasActive; 23453 active = document.activeElement; 23454 isActive = $menu.is(active); 23455 hasActive = $menu.has(active).length > 0; 23456 if (_.isMsie() && (isActive || hasActive)) { 23457 $e.preventDefault(); 23458 $e.stopImmediatePropagation(); 23459 _.defer(function() { 23460 $input.focus(); 23461 }); 23462 } 23463 }); 23464 $menu.on("mousedown.tt", function($e) { 23465 $e.preventDefault(); 23466 }); 23467 }, 23468 _onSelectableClicked: function onSelectableClicked(type, $el) { 23469 this.select($el); 23470 }, 23471 _onDatasetCleared: function onDatasetCleared() { 23472 this._updateHint(); 23473 }, 23474 _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) { 23475 this._updateHint(); 23476 this.eventBus.trigger("render", suggestions, async, dataset); 23477 }, 23478 _onAsyncRequested: function onAsyncRequested(type, dataset, query) { 23479 this.eventBus.trigger("asyncrequest", query, dataset); 23480 }, 23481 _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) { 23482 this.eventBus.trigger("asynccancel", query, dataset); 23483 }, 23484 _onAsyncReceived: function onAsyncReceived(type, dataset, query) { 23485 this.eventBus.trigger("asyncreceive", query, dataset); 23486 }, 23487 _onFocused: function onFocused() { 23488 this._minLengthMet() && this.menu.update(this.input.getQuery()); 23489 }, 23490 _onBlurred: function onBlurred() { 23491 if (this.input.hasQueryChangedSinceLastFocus()) { 23492 this.eventBus.trigger("change", this.input.getQuery()); 23493 } 23494 }, 23495 _onEnterKeyed: function onEnterKeyed(type, $e) { 23496 var $selectable; 23497 if ($selectable = this.menu.getActiveSelectable()) { 23498 this.select($selectable) && $e.preventDefault(); 23499 } 23500 }, 23501 _onTabKeyed: function onTabKeyed(type, $e) { 23502 var $selectable; 23503 if ($selectable = this.menu.getActiveSelectable()) { 23504 this.select($selectable) && $e.preventDefault(); 23505 } else if ($selectable = this.menu.getTopSelectable()) { 23506 this.autocomplete($selectable) && $e.preventDefault(); 23507 } 23508 }, 23509 _onEscKeyed: function onEscKeyed() { 23510 this.close(); 23511 }, 23512 _onUpKeyed: function onUpKeyed() { 23513 this.moveCursor(-1); 23514 }, 23515 _onDownKeyed: function onDownKeyed() { 23516 this.moveCursor(+1); 23517 }, 23518 _onLeftKeyed: function onLeftKeyed() { 23519 if (this.dir === "rtl" && this.input.isCursorAtEnd()) { 23520 this.autocomplete(this.menu.getTopSelectable()); 23521 } 23522 }, 23523 _onRightKeyed: function onRightKeyed() { 23524 if (this.dir === "ltr" && this.input.isCursorAtEnd()) { 23525 this.autocomplete(this.menu.getTopSelectable()); 23526 } 23527 }, 23528 _onQueryChanged: function onQueryChanged(e, query) { 23529 this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty(); 23530 }, 23531 _onWhitespaceChanged: function onWhitespaceChanged() { 23532 this._updateHint(); 23533 }, 23534 _onLangDirChanged: function onLangDirChanged(e, dir) { 23535 if (this.dir !== dir) { 23536 this.dir = dir; 23537 this.menu.setLanguageDirection(dir); 23538 } 23539 }, 23540 _openIfActive: function openIfActive() { 23541 this.isActive() && this.open(); 23542 }, 23543 _minLengthMet: function minLengthMet(query) { 23544 query = _.isString(query) ? query : this.input.getQuery() || ""; 23545 return query.length >= this.minLength; 23546 }, 23547 _updateHint: function updateHint() { 23548 var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match; 23549 $selectable = this.menu.getTopSelectable(); 23550 data = this.menu.getSelectableData($selectable); 23551 val = this.input.getInputValue(); 23552 if (data && !_.isBlankString(val) && !this.input.hasOverflow()) { 23553 query = Input.normalizeQuery(val); 23554 escapedQuery = _.escapeRegExChars(query); 23555 frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i"); 23556 match = frontMatchRegEx.exec(data.val); 23557 match && this.input.setHint(val + match[1]); 23558 } else { 23559 this.input.clearHint(); 23560 } 23561 }, 23562 isEnabled: function isEnabled() { 23563 return this.enabled; 23564 }, 23565 enable: function enable() { 23566 this.enabled = true; 23567 }, 23568 disable: function disable() { 23569 this.enabled = false; 23570 }, 23571 isActive: function isActive() { 23572 return this.active; 23573 }, 23574 activate: function activate() { 23575 if (this.isActive()) { 23576 return true; 23577 } else if (!this.isEnabled() || this.eventBus.before("active")) { 23578 return false; 23579 } else { 23580 this.active = true; 23581 this.eventBus.trigger("active"); 23582 return true; 23583 } 23584 }, 23585 deactivate: function deactivate() { 23586 if (!this.isActive()) { 23587 return true; 23588 } else if (this.eventBus.before("idle")) { 23589 return false; 23590 } else { 23591 this.active = false; 23592 this.close(); 23593 this.eventBus.trigger("idle"); 23594 return true; 23595 } 23596 }, 23597 isOpen: function isOpen() { 23598 return this.menu.isOpen(); 23599 }, 23600 open: function open() { 23601 if (!this.isOpen() && !this.eventBus.before("open")) { 23602 this.menu.open(); 23603 this._updateHint(); 23604 this.eventBus.trigger("open"); 23605 } 23606 return this.isOpen(); 23607 }, 23608 close: function close() { 23609 if (this.isOpen() && !this.eventBus.before("close")) { 23610 this.menu.close(); 23611 this.input.clearHint(); 23612 this.input.resetInputValue(); 23613 this.eventBus.trigger("close"); 23614 } 23615 return !this.isOpen(); 23616 }, 23617 setVal: function setVal(val) { 23618 this.input.setQuery(_.toStr(val)); 23619 }, 23620 getVal: function getVal() { 23621 return this.input.getQuery(); 23622 }, 23623 select: function select($selectable) { 23624 var data = this.menu.getSelectableData($selectable); 23625 if (data && !this.eventBus.before("select", data.obj)) { 23626 this.input.setQuery(data.val, true); 23627 this.eventBus.trigger("select", data.obj); 23628 this.close(); 23629 return true; 23630 } 23631 return false; 23632 }, 23633 autocomplete: function autocomplete($selectable) { 23634 var query, data, isValid; 23635 query = this.input.getQuery(); 23636 data = this.menu.getSelectableData($selectable); 23637 isValid = data && query !== data.val; 23638 if (isValid && !this.eventBus.before("autocomplete", data.obj)) { 23639 this.input.setQuery(data.val); 23640 this.eventBus.trigger("autocomplete", data.obj); 23641 return true; 23642 } 23643 return false; 23644 }, 23645 moveCursor: function moveCursor(delta) { 23646 var query, $candidate, data, payload, cancelMove; 23647 query = this.input.getQuery(); 23648 $candidate = this.menu.selectableRelativeToCursor(delta); 23649 data = this.menu.getSelectableData($candidate); 23650 payload = data ? data.obj : null; 23651 cancelMove = this._minLengthMet() && this.menu.update(query); 23652 if (!cancelMove && !this.eventBus.before("cursorchange", payload)) { 23653 this.menu.setCursor($candidate); 23654 if (data) { 23655 this.input.setInputValue(data.val); 23656 } else { 23657 this.input.resetInputValue(); 23658 this._updateHint(); 23659 } 23660 this.eventBus.trigger("cursorchange", payload); 23661 return true; 23662 } 23663 return false; 23664 }, 23665 destroy: function destroy() { 23666 this.input.destroy(); 23667 this.menu.destroy(); 23668 } 23669 }); 23670 return Typeahead; 23671 function c(ctx) { 23672 var methods = [].slice.call(arguments, 1); 23673 return function() { 23674 var args = [].slice.call(arguments); 23675 _.each(methods, function(method) { 23676 return ctx[method].apply(ctx, args); 23677 }); 23678 }; 23679 } 23680 }(); 23681 (function() { 23682 "use strict"; 23683 var old, keys, methods; 23684 old = $.fn.typeahead; 23685 keys = { 23686 www: "tt-www", 23687 attrs: "tt-attrs", 23688 typeahead: "tt-typeahead" 23689 }; 23690 methods = { 23691 initialize: function initialize(o, datasets) { 23692 var www; 23693 datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1); 23694 o = o || {}; 23695 www = WWW(o.classNames); 23696 return this.each(attach); 23697 function attach() { 23698 var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor; 23699 _.each(datasets, function(d) { 23700 d.highlight = !!o.highlight; 23701 }); 23702 $input = $(this); 23703 $wrapper = $(www.html.wrapper); 23704 $hint = $elOrNull(o.hint); 23705 $menu = $elOrNull(o.menu); 23706 defaultHint = o.hint !== false && !$hint; 23707 defaultMenu = o.menu !== false && !$menu; 23708 defaultHint && ($hint = buildHintFromInput($input, www)); 23709 defaultMenu && ($menu = $(www.html.menu).css(www.css.menu)); 23710 $hint && $hint.val(""); 23711 $input = prepInput($input, www); 23712 if (defaultHint || defaultMenu) { 23713 $wrapper.css(www.css.wrapper); 23714 $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint); 23715 $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null); 23716 } 23717 MenuConstructor = defaultMenu ? DefaultMenu : Menu; 23718 eventBus = new EventBus({ 23719 el: $input 23720 }); 23721 input = new Input({ 23722 hint: $hint, 23723 input: $input 23724 }, www); 23725 menu = new MenuConstructor({ 23726 node: $menu, 23727 datasets: datasets 23728 }, www); 23729 typeahead = new Typeahead({ 23730 input: input, 23731 menu: menu, 23732 eventBus: eventBus, 23733 minLength: o.minLength 23734 }, www); 23735 $input.data(keys.www, www); 23736 $input.data(keys.typeahead, typeahead); 23737 } 23738 }, 23739 isEnabled: function isEnabled() { 23740 var enabled; 23741 ttEach(this.first(), function(t) { 23742 enabled = t.isEnabled(); 23743 }); 23744 return enabled; 23745 }, 23746 enable: function enable() { 23747 ttEach(this, function(t) { 23748 t.enable(); 23749 }); 23750 return this; 23751 }, 23752 disable: function disable() { 23753 ttEach(this, function(t) { 23754 t.disable(); 23755 }); 23756 return this; 23757 }, 23758 isActive: function isActive() { 23759 var active; 23760 ttEach(this.first(), function(t) { 23761 active = t.isActive(); 23762 }); 23763 return active; 23764 }, 23765 activate: function activate() { 23766 ttEach(this, function(t) { 23767 t.activate(); 23768 }); 23769 return this; 23770 }, 23771 deactivate: function deactivate() { 23772 ttEach(this, function(t) { 23773 t.deactivate(); 23774 }); 23775 return this; 23776 }, 23777 isOpen: function isOpen() { 23778 var open; 23779 ttEach(this.first(), function(t) { 23780 open = t.isOpen(); 23781 }); 23782 return open; 23783 }, 23784 open: function open() { 23785 ttEach(this, function(t) { 23786 t.open(); 23787 }); 23788 return this; 23789 }, 23790 close: function close() { 23791 ttEach(this, function(t) { 23792 t.close(); 23793 }); 23794 return this; 23795 }, 23796 select: function select(el) { 23797 var success = false, $el = $(el); 23798 ttEach(this.first(), function(t) { 23799 success = t.select($el); 23800 }); 23801 return success; 23802 }, 23803 autocomplete: function autocomplete(el) { 23804 var success = false, $el = $(el); 23805 ttEach(this.first(), function(t) { 23806 success = t.autocomplete($el); 23807 }); 23808 return success; 23809 }, 23810 moveCursor: function moveCursoe(delta) { 23811 var success = false; 23812 ttEach(this.first(), function(t) { 23813 success = t.moveCursor(delta); 23814 }); 23815 return success; 23816 }, 23817 val: function val(newVal) { 23818 var query; 23819 if (!arguments.length) { 23820 ttEach(this.first(), function(t) { 23821 query = t.getVal(); 23822 }); 23823 return query; 23824 } else { 23825 ttEach(this, function(t) { 23826 t.setVal(newVal); 23827 }); 23828 return this; 23829 } 23830 }, 23831 destroy: function destroy() { 23832 ttEach(this, function(typeahead, $input) { 23833 revert($input); 23834 typeahead.destroy(); 23835 }); 23836 return this; 23837 } 23838 }; 23839 $.fn.typeahead = function(method) { 23840 if (methods[method]) { 23841 return methods[method].apply(this, [].slice.call(arguments, 1)); 23842 } else { 23843 return methods.initialize.apply(this, arguments); 23844 } 23845 }; 23846 $.fn.typeahead.noConflict = function noConflict() { 23847 $.fn.typeahead = old; 23848 return this; 23849 }; 23850 function ttEach($els, fn) { 23851 $els.each(function() { 23852 var $input = $(this), typeahead; 23853 (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input); 23854 }); 23855 } 23856 function buildHintFromInput($input, www) { 23857 return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({ 23858 autocomplete: "off", 23859 spellcheck: "false", 23860 tabindex: -1 23861 }); 23862 } 23863 function prepInput($input, www) { 23864 $input.data(keys.attrs, { 23865 dir: $input.attr("dir"), 23866 autocomplete: $input.attr("autocomplete"), 23867 spellcheck: $input.attr("spellcheck"), 23868 style: $input.attr("style") 23869 }); 23870 $input.addClass(www.classes.input).attr({ 23871 autocomplete: "off", 23872 spellcheck: false 23873 }); 23874 try { 23875 !$input.attr("dir") && $input.attr("dir", "auto"); 23876 } catch (e) {} 23877 return $input; 23878 } 23879 function getBackgroundStyles($el) { 23880 return { 23881 backgroundAttachment: $el.css("background-attachment"), 23882 backgroundClip: $el.css("background-clip"), 23883 backgroundColor: $el.css("background-color"), 23884 backgroundImage: $el.css("background-image"), 23885 backgroundOrigin: $el.css("background-origin"), 23886 backgroundPosition: $el.css("background-position"), 23887 backgroundRepeat: $el.css("background-repeat"), 23888 backgroundSize: $el.css("background-size") 23889 }; 23890 } 23891 function revert($input) { 23892 var www, $wrapper; 23893 www = $input.data(keys.www); 23894 $wrapper = $input.parent().filter(www.selectors.wrapper); 23895 _.each($input.data(keys.attrs), function(val, key) { 23896 _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); 23897 }); 23898 $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input); 23899 if ($wrapper.length) { 23900 $input.detach().insertAfter($wrapper); 23901 $wrapper.remove(); 23902 } 23903 } 23904 function $elOrNull(obj) { 23905 var isValid, $el; 23906 isValid = _.isJQuery(obj) || _.isElement(obj); 23907 $el = isValid ? $(obj).first() : []; 23908 return $el.length ? $el : null; 23909 } 23910 })(); 23911});
vendor: 47,604 bytes, lines 23911-25541
23911 23912/**! 23913 23914 @license 23915 handlebars v4.0.12 23916 23917Copyright (C) 2011-2017 by Yehuda Katz 23918 23919Permission is hereby granted, free of charge, to any person obtaining a copy 23920of this software and associated documentation files (the "Software"), to deal 23921in the Software without restriction, including without limitation the rights 23922to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23923copies of the Software, and to permit persons to whom the Software is 23924furnished to do so, subject to the following conditions: 23925 23926The above copyright notice and this permission notice shall be included in 23927all copies or substantial portions of the Software. 23928 23929THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23930IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23931FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23932AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23933LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23934OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23935THE SOFTWARE. 23936 23937*/ 23938(function webpackUniversalModuleDefinition(root, factory) { 23939 if(typeof exports === 'object' && typeof module === 'object') 23940 module.exports = factory(); 23941 else if(typeof define === 'function' && define.amd) 23942 define([], factory); 23943 else if(typeof exports === 'object') 23944 exports["Handlebars"] = factory(); 23945 else 23946 root["Handlebars"] = factory(); 23947})(this, function() { 23948return /******/ (function(modules) { // webpackBootstrap 23949/******/ // The module cache 23950/******/ var installedModules = {}; 23951 23952/******/ // The require function 23953/******/ function __webpack_require__(moduleId) { 23954 23955/******/ // Check if module is in cache 23956/******/ if(installedModules[moduleId]) 23957/******/ return installedModules[moduleId].exports; 23958 23959/******/ // Create a new module (and put it into the cache) 23960/******/ var module = installedModules[moduleId] = { 23961/******/ exports: {}, 23962/******/ id: moduleId, 23963/******/ loaded: false 23964/******/ }; 23965 23966/******/ // Execute the module function 23967/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 23968 23969/******/ // Flag the module as loaded 23970/******/ module.loaded = true; 23971 23972/******/ // Return the exports of the module 23973/******/ return module.exports; 23974/******/ } 23975 23976 23977/******/ // expose the modules object (__webpack_modules__) 23978/******/ __webpack_require__.m = modules; 23979 23980/******/ // expose the module cache 23981/******/ __webpack_require__.c = installedModules; 23982 23983/******/ // __webpack_public_path__ 23984/******/ __webpack_require__.p = ""; 23985 23986/******/ // Load entry module and return exports 23987/******/ return __webpack_require__(0); 23988/******/ }) 23989/************************************************************************/ 23990/******/ ([ 23991/* 0 */ 23992/***/ (function(module, exports, __webpack_require__) { 23993 23994 'use strict'; 23995 23996 var _interopRequireDefault = __webpack_require__(1)['default']; 23997 23998 exports.__esModule = true; 23999 24000 var _handlebarsRuntime = __webpack_require__(2); 24001 24002 var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime); 24003 24004 // Compiler imports 24005 24006 var _handlebarsCompilerAst = __webpack_require__(35); 24007 24008 var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst); 24009 24010 var _handlebarsCompilerBase = __webpack_require__(36); 24011 24012 var _handlebarsCompilerCompiler = __webpack_require__(41); 24013 24014 var _handlebarsCompilerJavascriptCompiler = __webpack_require__(42); 24015 24016 var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler); 24017 24018 var _handlebarsCompilerVisitor = __webpack_require__(39); 24019 24020 var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor); 24021 24022 var _handlebarsNoConflict = __webpack_require__(34); 24023 24024 var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); 24025 24026 var _create = _handlebarsRuntime2['default'].create; 24027 function create() { 24028 var hb = _create(); 24029 24030 hb.compile = function (input, options) { 24031 return _handlebarsCompilerCompiler.compile(input, options, hb); 24032 }; 24033 hb.precompile = function (input, options) { 24034 return _handlebarsCompilerCompiler.precompile(input, options, hb); 24035 }; 24036 24037 hb.AST = _handlebarsCompilerAst2['default']; 24038 hb.Compiler = _handlebarsCompilerCompiler.Compiler; 24039 hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default']; 24040 hb.Parser = _handlebarsCompilerBase.parser; 24041 hb.parse = _handlebarsCompilerBase.parse; 24042 24043 return hb; 24044 } 24045 24046 var inst = create(); 24047 inst.create = create; 24048 24049 _handlebarsNoConflict2['default'](inst); 24050 24051 inst.Visitor = _handlebarsCompilerVisitor2['default']; 24052 24053 inst['default'] = inst; 24054 24055 exports['default'] = inst; 24056 module.exports = exports['default']; 24057 24058/***/ }), 24059/* 1 */ 24060/***/ (function(module, exports) { 24061 24062 "use strict"; 24063 24064 exports["default"] = function (obj) { 24065 return obj && obj.__esModule ? obj : { 24066 "default": obj 24067 }; 24068 }; 24069 24070 exports.__esModule = true; 24071 24072/***/ }), 24073/* 2 */ 24074/***/ (function(module, exports, __webpack_require__) { 24075 24076 'use strict'; 24077 24078 var _interopRequireWildcard = __webpack_require__(3)['default']; 24079 24080 var _interopRequireDefault = __webpack_require__(1)['default']; 24081 24082 exports.__esModule = true; 24083 24084 var _handlebarsBase = __webpack_require__(4); 24085 24086 var base = _interopRequireWildcard(_handlebarsBase); 24087 24088 // Each of these augment the Handlebars object. No need to setup here. 24089 // (This is done to easily share code between commonjs and browse envs) 24090 24091 var _handlebarsSafeString = __webpack_require__(21); 24092 24093 var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString); 24094 24095 var _handlebarsException = __webpack_require__(6); 24096 24097 var _handlebarsException2 = _interopRequireDefault(_handlebarsException); 24098 24099 var _handlebarsUtils = __webpack_require__(5); 24100 24101 var Utils = _interopRequireWildcard(_handlebarsUtils); 24102 24103 var _handlebarsRuntime = __webpack_require__(22); 24104 24105 var runtime = _interopRequireWildcard(_handlebarsRuntime); 24106 24107 var _handlebarsNoConflict = __webpack_require__(34); 24108 24109 var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); 24110 24111 // For compatibility and usage outside of module systems, make the Handlebars object a namespace 24112 function create() { 24113 var hb = new base.HandlebarsEnvironment(); 24114 24115 Utils.extend(hb, base); 24116 hb.SafeString = _handlebarsSafeString2['default']; 24117 hb.Exception = _handlebarsException2['default']; 24118 hb.Utils = Utils; 24119 hb.escapeExpression = Utils.escapeExpression; 24120 24121 hb.VM = runtime; 24122 hb.template = function (spec) { 24123 return runtime.template(spec, hb); 24124 }; 24125 24126 return hb; 24127 } 24128 24129 var inst = create(); 24130 inst.create = create; 24131 24132 _handlebarsNoConflict2['default'](inst); 24133 24134 inst['default'] = inst; 24135 24136 exports['default'] = inst; 24137 module.exports = exports['default']; 24138 24139/***/ }), 24140/* 3 */ 24141/***/ (function(module, exports) { 24142 24143 "use strict"; 24144 24145 exports["default"] = function (obj) { 24146 if (obj && obj.__esModule) { 24147 return obj; 24148 } else { 24149 var newObj = {}; 24150 24151 if (obj != null) { 24152 for (var key in obj) { 24153 if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; 24154 } 24155 } 24156 24157 newObj["default"] = obj; 24158 return newObj; 24159 } 24160 }; 24161 24162 exports.__esModule = true; 24163 24164/***/ }), 24165/* 4 */ 24166/***/ (function(module, exports, __webpack_require__) { 24167 24168 'use strict'; 24169 24170 var _interopRequireDefault = __webpack_require__(1)['default']; 24171 24172 exports.__esModule = true; 24173 exports.HandlebarsEnvironment = HandlebarsEnvironment; 24174 24175 var _utils = __webpack_require__(5); 24176 24177 var _exception = __webpack_require__(6); 24178 24179 var _exception2 = _interopRequireDefault(_exception); 24180 24181 var _helpers = __webpack_require__(10); 24182 24183 var _decorators = __webpack_require__(18); 24184 24185 var _logger = __webpack_require__(20); 24186 24187 var _logger2 = _interopRequireDefault(_logger); 24188 24189 var VERSION = '4.0.12'; 24190 exports.VERSION = VERSION; 24191 var COMPILER_REVISION = 7; 24192 24193 exports.COMPILER_REVISION = COMPILER_REVISION; 24194 var REVISION_CHANGES = { 24195 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it 24196 2: '== 1.0.0-rc.3', 24197 3: '== 1.0.0-rc.4', 24198 4: '== 1.x.x', 24199 5: '== 2.0.0-alpha.x', 24200 6: '>= 2.0.0-beta.1', 24201 7: '>= 4.0.0' 24202 }; 24203 24204 exports.REVISION_CHANGES = REVISION_CHANGES; 24205 var objectType = '[object Object]'; 24206 24207 function HandlebarsEnvironment(helpers, partials, decorators) { 24208 this.helpers = helpers || {}; 24209 this.partials = partials || {}; 24210 this.decorators = decorators || {}; 24211 24212 _helpers.registerDefaultHelpers(this); 24213 _decorators.registerDefaultDecorators(this); 24214 } 24215 24216 HandlebarsEnvironment.prototype = { 24217 constructor: HandlebarsEnvironment, 24218 24219 logger: _logger2['default'], 24220 log: _logger2['default'].log, 24221 24222 registerHelper: function registerHelper(name, fn) { 24223 if (_utils.toString.call(name) === objectType) { 24224 if (fn) { 24225 throw new _exception2['default']('Arg not supported with multiple helpers'); 24226 } 24227 _utils.extend(this.helpers, name); 24228 } else { 24229 this.helpers[name] = fn; 24230 } 24231 }, 24232 unregisterHelper: function unregisterHelper(name) { 24233 delete this.helpers[name]; 24234 }, 24235 24236 registerPartial: function registerPartial(name, partial) { 24237 if (_utils.toString.call(name) === objectType) { 24238 _utils.extend(this.partials, name); 24239 } else { 24240 if (typeof partial === 'undefined') { 24241 throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined'); 24242 } 24243 this.partials[name] = partial; 24244 } 24245 }, 24246 unregisterPartial: function unregisterPartial(name) { 24247 delete this.partials[name]; 24248 }, 24249 24250 registerDecorator: function registerDecorator(name, fn) { 24251 if (_utils.toString.call(name) === objectType) { 24252 if (fn) { 24253 throw new _exception2['default']('Arg not supported with multiple decorators'); 24254 } 24255 _utils.extend(this.decorators, name); 24256 } else { 24257 this.decorators[name] = fn; 24258 } 24259 }, 24260 unregisterDecorator: function unregisterDecorator(name) { 24261 delete this.decorators[name]; 24262 } 24263 }; 24264 24265 var log = _logger2['default'].log; 24266 24267 exports.log = log; 24268 exports.createFrame = _utils.createFrame; 24269 exports.logger = _logger2['default']; 24270 24271/***/ }), 24272/* 5 */ 24273/***/ (function(module, exports) { 24274 24275 'use strict'; 24276 24277 exports.__esModule = true; 24278 exports.extend = extend; 24279 exports.indexOf = indexOf; 24280 exports.escapeExpression = escapeExpression; 24281 exports.isEmpty = isEmpty; 24282 exports.createFrame = createFrame; 24283 exports.blockParams = blockParams; 24284 exports.appendContextPath = appendContextPath; 24285 var escape = { 24286 '&': '&', 24287 '<': '<', 24288 '>': '>', 24289 '"': '"', 24290 "'": ''', 24291 '`': '`', 24292 '=': '=' 24293 }; 24294 24295 var badChars = /[&<>"'`=]/g, 24296 possible = /[&<>"'`=]/; 24297 24298 function escapeChar(chr) { 24299 return escape[chr]; 24300 } 24301 24302 function extend(obj /* , ...source */) { 24303 for (var i = 1; i < arguments.length; i++) { 24304 for (var key in arguments[i]) { 24305 if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { 24306 obj[key] = arguments[i][key]; 24307 } 24308 } 24309 } 24310 24311 return obj; 24312 } 24313 24314 var toString = Object.prototype.toString; 24315 24316 exports.toString = toString; 24317 // Sourced from lodash 24318 // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt 24319 /* eslint-disable func-style */ 24320 var isFunction = function isFunction(value) { 24321 return typeof value === 'function'; 24322 }; 24323 // fallback for older versions of Chrome and Safari 24324 /* istanbul ignore next */ 24325 if (isFunction(/x/)) { 24326 exports.isFunction = isFunction = function (value) { 24327 return typeof value === 'function' && toString.call(value) === '[object Function]'; 24328 }; 24329 } 24330 exports.isFunction = isFunction; 24331 24332 /* eslint-enable func-style */ 24333 24334 /* istanbul ignore next */ 24335 var isArray = Array.isArray || function (value) { 24336 return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; 24337 }; 24338 24339 exports.isArray = isArray; 24340 // Older IE versions do not directly support indexOf so we must implement our own, sadly. 24341 24342 function indexOf(array, value) { 24343 for (var i = 0, len = array.length; i < len; i++) { 24344 if (array[i] === value) { 24345 return i; 24346 } 24347 } 24348 return -1; 24349 } 24350 24351 function escapeExpression(string) { 24352 if (typeof string !== 'string') { 24353 // don't escape SafeStrings, since they're already safe 24354 if (string && string.toHTML) { 24355 return string.toHTML(); 24356 } else if (string == null) { 24357 return ''; 24358 } else if (!string) { 24359 return string + ''; 24360 } 24361 24362 // Force a string conversion as this will be done by the append regardless and 24363 // the regex test will do this transparently behind the scenes, causing issues if 24364 // an object's to string has escaped characters in it. 24365 string = '' + string; 24366 } 24367 24368 if (!possible.test(string)) { 24369 return string; 24370 } 24371 return string.replace(badChars, escapeChar); 24372 } 24373 24374 function isEmpty(value) { 24375 if (!value && value !== 0) { 24376 return true; 24377 } else if (isArray(value) && value.length === 0) { 24378 return true; 24379 } else { 24380 return false; 24381 } 24382 } 24383 24384 function createFrame(object) { 24385 var frame = extend({}, object); 24386 frame._parent = object; 24387 return frame; 24388 } 24389 24390 function blockParams(params, ids) { 24391 params.path = ids; 24392 return params; 24393 } 24394 24395 function appendContextPath(contextPath, id) { 24396 return (contextPath ? contextPath + '.' : '') + id; 24397 } 24398 24399/***/ }), 24400/* 6 */ 24401/***/ (function(module, exports, __webpack_require__) { 24402 24403 'use strict'; 24404 24405 var _Object$defineProperty = __webpack_require__(7)['default']; 24406 24407 exports.__esModule = true; 24408 24409 var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; 24410 24411 function Exception(message, node) { 24412 var loc = node && node.loc, 24413 line = undefined, 24414 column = undefined; 24415 if (loc) { 24416 line = loc.start.line; 24417 column = loc.start.column; 24418 24419 message += ' - ' + line + ':' + column; 24420 } 24421 24422 var tmp = Error.prototype.constructor.call(this, message); 24423 24424 // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. 24425 for (var idx = 0; idx < errorProps.length; idx++) { 24426 this[errorProps[idx]] = tmp[errorProps[idx]]; 24427 } 24428 24429 /* istanbul ignore else */ 24430 if (Error.captureStackTrace) { 24431 Error.captureStackTrace(this, Exception); 24432 } 24433 24434 try { 24435 if (loc) { 24436 this.lineNumber = line; 24437 24438 // Work around issue under safari where we can't directly set the column value 24439 /* istanbul ignore next */ 24440 if (_Object$defineProperty) { 24441 Object.defineProperty(this, 'column', { 24442 value: column, 24443 enumerable: true 24444 }); 24445 } else { 24446 this.column = column; 24447 } 24448 } 24449 } catch (nop) { 24450 /* Ignore if the browser is very particular */ 24451 } 24452 } 24453 24454 Exception.prototype = new Error(); 24455 24456 exports['default'] = Exception; 24457 module.exports = exports['default']; 24458 24459/***/ }), 24460/* 7 */ 24461/***/ (function(module, exports, __webpack_require__) { 24462 24463 module.exports = { "default": __webpack_require__(8), __esModule: true }; 24464 24465/***/ }), 24466/* 8 */ 24467/***/ (function(module, exports, __webpack_require__) { 24468 24469 var $ = __webpack_require__(9); 24470 module.exports = function defineProperty(it, key, desc){ 24471 return $.setDesc(it, key, desc); 24472 }; 24473 24474/***/ }), 24475/* 9 */ 24476/***/ (function(module, exports) { 24477 24478 var $Object = Object; 24479 module.exports = { 24480 create: $Object.create, 24481 getProto: $Object.getPrototypeOf, 24482 isEnum: {}.propertyIsEnumerable, 24483 getDesc: $Object.getOwnPropertyDescriptor, 24484 setDesc: $Object.defineProperty, 24485 setDescs: $Object.defineProperties, 24486 getKeys: $Object.keys, 24487 getNames: $Object.getOwnPropertyNames, 24488 getSymbols: $Object.getOwnPropertySymbols, 24489 each: [].forEach 24490 }; 24491 24492/***/ }), 24493/* 10 */ 24494/***/ (function(module, exports, __webpack_require__) { 24495 24496 'use strict'; 24497 24498 var _interopRequireDefault = __webpack_require__(1)['default']; 24499 24500 exports.__esModule = true; 24501 exports.registerDefaultHelpers = registerDefaultHelpers; 24502 24503 var _helpersBlockHelperMissing = __webpack_require__(11); 24504 24505 var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing); 24506 24507 var _helpersEach = __webpack_require__(12); 24508 24509 var _helpersEach2 = _interopRequireDefault(_helpersEach); 24510 24511 var _helpersHelperMissing = __webpack_require__(13); 24512 24513 var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing); 24514 24515 var _helpersIf = __webpack_require__(14); 24516 24517 var _helpersIf2 = _interopRequireDefault(_helpersIf); 24518 24519 var _helpersLog = __webpack_require__(15); 24520 24521 var _helpersLog2 = _interopRequireDefault(_helpersLog); 24522 24523 var _helpersLookup = __webpack_require__(16); 24524 24525 var _helpersLookup2 = _interopRequireDefault(_helpersLookup); 24526 24527 var _helpersWith = __webpack_require__(17); 24528 24529 var _helpersWith2 = _interopRequireDefault(_helpersWith); 24530 24531 function registerDefaultHelpers(instance) { 24532 _helpersBlockHelperMissing2['default'](instance); 24533 _helpersEach2['default'](instance); 24534 _helpersHelperMissing2['default'](instance); 24535 _helpersIf2['default'](instance); 24536 _helpersLog2['default'](instance); 24537 _helpersLookup2['default'](instance); 24538 _helpersWith2['default'](instance); 24539 } 24540 24541/***/ }), 24542/* 11 */ 24543/***/ (function(module, exports, __webpack_require__) { 24544 24545 'use strict'; 24546 24547 exports.__esModule = true; 24548 24549 var _utils = __webpack_require__(5); 24550 24551 exports['default'] = function (instance) { 24552 instance.registerHelper('blockHelperMissing', function (context, options) { 24553 var inverse = options.inverse, 24554 fn = options.fn; 24555 24556 if (context === true) { 24557 return fn(this); 24558 } else if (context === false || context == null) { 24559 return inverse(this); 24560 } else if (_utils.isArray(context)) { 24561 if (context.length > 0) { 24562 if (options.ids) { 24563 options.ids = [options.name]; 24564 } 24565 24566 return instance.helpers.each(context, options); 24567 } else { 24568 return inverse(this); 24569 } 24570 } else { 24571 if (options.data && options.ids) { 24572 var data = _utils.createFrame(options.data); 24573 data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); 24574 options = { data: data }; 24575 } 24576 24577 return fn(context, options); 24578 } 24579 }); 24580 }; 24581 24582 module.exports = exports['default']; 24583 24584/***/ }), 24585/* 12 */ 24586/***/ (function(module, exports, __webpack_require__) { 24587 24588 'use strict'; 24589 24590 var _interopRequireDefault = __webpack_require__(1)['default']; 24591 24592 exports.__esModule = true; 24593 24594 var _utils = __webpack_require__(5); 24595 24596 var _exception = __webpack_require__(6); 24597 24598 var _exception2 = _interopRequireDefault(_exception); 24599 24600 exports['default'] = function (instance) { 24601 instance.registerHelper('each', function (context, options) { 24602 if (!options) { 24603 throw new _exception2['default']('Must pass iterator to #each'); 24604 } 24605 24606 var fn = options.fn, 24607 inverse = options.inverse, 24608 i = 0, 24609 ret = '', 24610 data = undefined, 24611 contextPath = undefined; 24612 24613 if (options.data && options.ids) { 24614 contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; 24615 } 24616 24617 if (_utils.isFunction(context)) { 24618 context = context.call(this); 24619 } 24620 24621 if (options.data) { 24622 data = _utils.createFrame(options.data); 24623 } 24624 24625 function execIteration(field, index, last) { 24626 if (data) { 24627 data.key = field; 24628 data.index = index; 24629 data.first = index === 0; 24630 data.last = !!last; 24631 24632 if (contextPath) { 24633 data.contextPath = contextPath + field; 24634 } 24635 } 24636 24637 ret = ret + fn(context[field], { 24638 data: data, 24639 blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) 24640 }); 24641 } 24642 24643 if (context && typeof context === 'object') { 24644 if (_utils.isArray(context)) { 24645 for (var j = context.length; i < j; i++) { 24646 if (i in context) { 24647 execIteration(i, i, i === context.length - 1); 24648 } 24649 } 24650 } else { 24651 var priorKey = undefined; 24652 24653 for (var key in context) { 24654 if (context.hasOwnProperty(key)) { 24655 // We're running the iterations one step out of sync so we can detect 24656 // the last iteration without have to scan the object twice and create 24657 // an itermediate keys array. 24658 if (priorKey !== undefined) { 24659 execIteration(priorKey, i - 1); 24660 } 24661 priorKey = key; 24662 i++; 24663 } 24664 } 24665 if (priorKey !== undefined) { 24666 execIteration(priorKey, i - 1, true); 24667 } 24668 } 24669 } 24670 24671 if (i === 0) { 24672 ret = inverse(this); 24673 } 24674 24675 return ret; 24676 }); 24677 }; 24678 24679 module.exports = exports['default']; 24680 24681/***/ }), 24682/* 13 */ 24683/***/ (function(module, exports, __webpack_require__) { 24684 24685 'use strict'; 24686 24687 var _interopRequireDefault = __webpack_require__(1)['default']; 24688 24689 exports.__esModule = true; 24690 24691 var _exception = __webpack_require__(6); 24692 24693 var _exception2 = _interopRequireDefault(_exception); 24694 24695 exports['default'] = function (instance) { 24696 instance.registerHelper('helperMissing', function () /* [args, ]options */{ 24697 if (arguments.length === 1) { 24698 // A missing field in a {{foo}} construct. 24699 return undefined; 24700 } else { 24701 // Someone is actually trying to call something, blow up. 24702 throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); 24703 } 24704 }); 24705 }; 24706 24707 module.exports = exports['default']; 24708 24709/***/ }), 24710/* 14 */ 24711/***/ (function(module, exports, __webpack_require__) { 24712 24713 'use strict'; 24714 24715 exports.__esModule = true; 24716 24717 var _utils = __webpack_require__(5); 24718 24719 exports['default'] = function (instance) { 24720 instance.registerHelper('if', function (conditional, options) { 24721 if (_utils.isFunction(conditional)) { 24722 conditional = conditional.call(this); 24723 } 24724 24725 // Default behavior is to render the positive path if the value is truthy and not empty. 24726 // The `includeZero` option may be set to treat the condtional as purely not empty based on the 24727 // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. 24728 if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { 24729 return options.inverse(this); 24730 } else { 24731 return options.fn(this); 24732 } 24733 }); 24734 24735 instance.registerHelper('unless', function (conditional, options) { 24736 return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash }); 24737 }); 24738 }; 24739 24740 module.exports = exports['default']; 24741 24742/***/ }), 24743/* 15 */ 24744/***/ (function(module, exports) { 24745 24746 'use strict'; 24747 24748 exports.__esModule = true; 24749 24750 exports['default'] = function (instance) { 24751 instance.registerHelper('log', function () /* message, options */{ 24752 var args = [undefined], 24753 options = arguments[arguments.length - 1]; 24754 for (var i = 0; i < arguments.length - 1; i++) { 24755 args.push(arguments[i]); 24756 } 24757 24758 var level = 1; 24759 if (options.hash.level != null) { 24760 level = options.hash.level; 24761 } else if (options.data && options.data.level != null) { 24762 level = options.data.level; 24763 } 24764 args[0] = level; 24765 24766 instance.log.apply(instance, args); 24767 }); 24768 }; 24769 24770 module.exports = exports['default']; 24771 24772/***/ }), 24773/* 16 */ 24774/***/ (function(module, exports) { 24775 24776 'use strict'; 24777 24778 exports.__esModule = true; 24779 24780 exports['default'] = function (instance) { 24781 instance.registerHelper('lookup', function (obj, field) { 24782 return obj && obj[field]; 24783 }); 24784 }; 24785 24786 module.exports = exports['default']; 24787 24788/***/ }), 24789/* 17 */ 24790/***/ (function(module, exports, __webpack_require__) { 24791 24792 'use strict'; 24793 24794 exports.__esModule = true; 24795 24796 var _utils = __webpack_require__(5); 24797 24798 exports['default'] = function (instance) { 24799 instance.registerHelper('with', function (context, options) { 24800 if (_utils.isFunction(context)) { 24801 context = context.call(this); 24802 } 24803 24804 var fn = options.fn; 24805 24806 if (!_utils.isEmpty(context)) { 24807 var data = options.data; 24808 if (options.data && options.ids) { 24809 data = _utils.createFrame(options.data); 24810 data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); 24811 } 24812 24813 return fn(context, { 24814 data: data, 24815 blockParams: _utils.blockParams([context], [data && data.contextPath]) 24816 }); 24817 } else { 24818 return options.inverse(this); 24819 } 24820 }); 24821 }; 24822 24823 module.exports = exports['default']; 24824 24825/***/ }), 24826/* 18 */ 24827/***/ (function(module, exports, __webpack_require__) { 24828 24829 'use strict'; 24830 24831 var _interopRequireDefault = __webpack_require__(1)['default']; 24832 24833 exports.__esModule = true; 24834 exports.registerDefaultDecorators = registerDefaultDecorators; 24835 24836 var _decoratorsInline = __webpack_require__(19); 24837 24838 var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline); 24839 24840 function registerDefaultDecorators(instance) { 24841 _decoratorsInline2['default'](instance); 24842 } 24843 24844/***/ }), 24845/* 19 */ 24846/***/ (function(module, exports, __webpack_require__) { 24847 24848 'use strict'; 24849 24850 exports.__esModule = true; 24851 24852 var _utils = __webpack_require__(5); 24853 24854 exports['default'] = function (instance) { 24855 instance.registerDecorator('inline', function (fn, props, container, options) { 24856 var ret = fn; 24857 if (!props.partials) { 24858 props.partials = {}; 24859 ret = function (context, options) { 24860 // Create a new partials stack frame prior to exec. 24861 var original = container.partials; 24862 container.partials = _utils.extend({}, original, props.partials); 24863 var ret = fn(context, options); 24864 container.partials = original; 24865 return ret; 24866 }; 24867 } 24868 24869 props.partials[options.args[0]] = options.fn; 24870 24871 return ret; 24872 }); 24873 }; 24874 24875 module.exports = exports['default']; 24876 24877/***/ }), 24878/* 20 */ 24879/***/ (function(module, exports, __webpack_require__) { 24880 24881 'use strict'; 24882 24883 exports.__esModule = true; 24884 24885 var _utils = __webpack_require__(5); 24886 24887 var logger = { 24888 methodMap: ['debug', 'info', 'warn', 'error'], 24889 level: 'info', 24890 24891 // Maps a given level value to the `methodMap` indexes above. 24892 lookupLevel: function lookupLevel(level) { 24893 if (typeof level === 'string') { 24894 var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); 24895 if (levelMap >= 0) { 24896 level = levelMap; 24897 } else { 24898 level = parseInt(level, 10); 24899 } 24900 } 24901 24902 return level; 24903 }, 24904 24905 // Can be overridden in the host environment 24906 log: function log(level) { 24907 level = logger.lookupLevel(level); 24908 24909 if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { 24910 var method = logger.methodMap[level]; 24911 if (!console[method]) { 24912 // eslint-disable-line no-console 24913 method = 'log'; 24914 } 24915 24916 for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 24917 message[_key - 1] = arguments[_key]; 24918 } 24919 24920 console[method].apply(console, message); // eslint-disable-line no-console 24921 } 24922 } 24923 }; 24924 24925 exports['default'] = logger; 24926 module.exports = exports['default']; 24927 24928/***/ }), 24929/* 21 */ 24930/***/ (function(module, exports) { 24931 24932 // Build out our basic SafeString type 24933 'use strict'; 24934 24935 exports.__esModule = true; 24936 function SafeString(string) { 24937 this.string = string; 24938 } 24939 24940 SafeString.prototype.toString = SafeString.prototype.toHTML = function () { 24941 return '' + this.string; 24942 }; 24943 24944 exports['default'] = SafeString; 24945 module.exports = exports['default']; 24946 24947/***/ }), 24948/* 22 */ 24949/***/ (function(module, exports, __webpack_require__) { 24950 24951 'use strict'; 24952 24953 var _Object$seal = __webpack_require__(23)['default']; 24954 24955 var _interopRequireWildcard = __webpack_require__(3)['default']; 24956 24957 var _interopRequireDefault = __webpack_require__(1)['default']; 24958 24959 exports.__esModule = true; 24960 exports.checkRevision = checkRevision; 24961 exports.template = template; 24962 exports.wrapProgram = wrapProgram; 24963 exports.resolvePartial = resolvePartial; 24964 exports.invokePartial = invokePartial; 24965 exports.noop = noop; 24966 24967 var _utils = __webpack_require__(5); 24968 24969 var Utils = _interopRequireWildcard(_utils); 24970 24971 var _exception = __webpack_require__(6); 24972 24973 var _exception2 = _interopRequireDefault(_exception); 24974 24975 var _base = __webpack_require__(4); 24976 24977 function checkRevision(compilerInfo) { 24978 var compilerRevision = compilerInfo && compilerInfo[0] || 1, 24979 currentRevision = _base.COMPILER_REVISION; 24980 24981 if (compilerRevision !== currentRevision) { 24982 if (compilerRevision < currentRevision) { 24983 var runtimeVersions = _base.REVISION_CHANGES[currentRevision], 24984 compilerVersions = _base.REVISION_CHANGES[compilerRevision]; 24985 throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); 24986 } else { 24987 // Use the embedded version info since the runtime doesn't know about this revision yet 24988 throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); 24989 } 24990 } 24991 } 24992 24993 function template(templateSpec, env) { 24994 /* istanbul ignore next */ 24995 if (!env) { 24996 throw new _exception2['default']('No environment passed to template'); 24997 } 24998 if (!templateSpec || !templateSpec.main) { 24999 throw new _exception2['default']('Unknown template object: ' + typeof templateSpec); 25000 } 25001 25002 templateSpec.main.decorator = templateSpec.main_d; 25003 25004 // Note: Using env.VM references rather than local var references throughout this section to allow 25005 // for external users to override these as psuedo-supported APIs. 25006 env.VM.checkRevision(templateSpec.compiler); 25007 25008 function invokePartialWrapper(partial, context, options) { 25009 if (options.hash) { 25010 context = Utils.extend({}, context, options.hash); 25011 if (options.ids) { 25012 options.ids[0] = true; 25013 } 25014 } 25015 25016 partial = env.VM.resolvePartial.call(this, partial, context, options); 25017 var result = env.VM.invokePartial.call(this, partial, context, options); 25018 25019 if (result == null && env.compile) { 25020 options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); 25021 result = options.partials[options.name](context, options); 25022 } 25023 if (result != null) { 25024 if (options.indent) { 25025 var lines = result.split('\n'); 25026 for (var i = 0, l = lines.length; i < l; i++) { 25027 if (!lines[i] && i + 1 === l) { 25028 break; 25029 } 25030 25031 lines[i] = options.indent + lines[i]; 25032 } 25033 result = lines.join('\n'); 25034 } 25035 return result; 25036 } else { 25037 throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); 25038 } 25039 } 25040 25041 // Just add water 25042 var container = { 25043 strict: function strict(obj, name) { 25044 if (!(name in obj)) { 25045 throw new _exception2['default']('"' + name + '" not defined in ' + obj); 25046 } 25047 return obj[name]; 25048 }, 25049 lookup: function lookup(depths, name) { 25050 var len = depths.length; 25051 for (var i = 0; i < len; i++) { 25052 if (depths[i] && depths[i][name] != null) { 25053 return depths[i][name]; 25054 } 25055 } 25056 }, 25057 lambda: function lambda(current, context) { 25058 return typeof current === 'function' ? current.call(context) : current; 25059 }, 25060 25061 escapeExpression: Utils.escapeExpression, 25062 invokePartial: invokePartialWrapper, 25063 25064 fn: function fn(i) { 25065 var ret = templateSpec[i]; 25066 ret.decorator = templateSpec[i + '_d']; 25067 return ret; 25068 }, 25069 25070 programs: [], 25071 program: function program(i, data, declaredBlockParams, blockParams, depths) { 25072 var programWrapper = this.programs[i], 25073 fn = this.fn(i); 25074 if (data || depths || blockParams || declaredBlockParams) { 25075 programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); 25076 } else if (!programWrapper) { 25077 programWrapper = this.programs[i] = wrapProgram(this, i, fn); 25078 } 25079 return programWrapper; 25080 }, 25081 25082 data: function data(value, depth) { 25083 while (value && depth--) { 25084 value = value._parent; 25085 } 25086 return value; 25087 }, 25088 merge: function merge(param, common) { 25089 var obj = param || common; 25090 25091 if (param && common && param !== common) { 25092 obj = Utils.extend({}, common, param); 25093 } 25094 25095 return obj; 25096 }, 25097 // An empty object to use as replacement for null-contexts 25098 nullContext: _Object$seal({}), 25099 25100 noop: env.VM.noop, 25101 compilerInfo: templateSpec.compiler 25102 }; 25103 25104 function ret(context) { 25105 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 25106 25107 var data = options.data; 25108 25109 ret._setup(options); 25110 if (!options.partial && templateSpec.useData) { 25111 data = initData(context, data); 25112 } 25113 var depths = undefined, 25114 blockParams = templateSpec.useBlockParams ? [] : undefined; 25115 if (templateSpec.useDepths) { 25116 if (options.depths) { 25117 depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; 25118 } else { 25119 depths = [context]; 25120 } 25121 } 25122 25123 function main(context /*, options*/) { 25124 return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); 25125 } 25126 main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); 25127 return main(context, options); 25128 } 25129 ret.isTop = true; 25130 25131 ret._setup = function (options) { 25132 if (!options.partial) { 25133 container.helpers = container.merge(options.helpers, env.helpers); 25134 25135 if (templateSpec.usePartial) { 25136 container.partials = container.merge(options.partials, env.partials); 25137 } 25138 if (templateSpec.usePartial || templateSpec.useDecorators) { 25139 container.decorators = container.merge(options.decorators, env.decorators); 25140 } 25141 } else { 25142 container.helpers = options.helpers; 25143 container.partials = options.partials; 25144 container.decorators = options.decorators; 25145 } 25146 }; 25147 25148 ret._child = function (i, data, blockParams, depths) { 25149 if (templateSpec.useBlockParams && !blockParams) { 25150 throw new _exception2['default']('must pass block params'); 25151 } 25152 if (templateSpec.useDepths && !depths) { 25153 throw new _exception2['default']('must pass parent depths'); 25154 } 25155 25156 return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); 25157 }; 25158 return ret; 25159 } 25160 25161 function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { 25162 function prog(context) { 25163 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 25164 25165 var currentDepths = depths; 25166 if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) { 25167 currentDepths = [context].concat(depths); 25168 } 25169 25170 return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); 25171 } 25172 25173 prog = executeDecorators(fn, prog, container, depths, data, blockParams); 25174 25175 prog.program = i; 25176 prog.depth = depths ? depths.length : 0; 25177 prog.blockParams = declaredBlockParams || 0; 25178 return prog; 25179 } 25180 25181 function resolvePartial(partial, context, options) { 25182 if (!partial) { 25183 if (options.name === '@partial-block') { 25184 partial = options.data['partial-block']; 25185 } else { 25186 partial = options.partials[options.name]; 25187 } 25188 } else if (!partial.call && !options.name) { 25189 // This is a dynamic partial that returned a string 25190 options.name = partial; 25191 partial = options.partials[partial]; 25192 } 25193 return partial; 25194 } 25195 25196 function invokePartial(partial, context, options) { 25197 // Use the current closure context to save the partial-block if this partial 25198 var currentPartialBlock = options.data && options.data['partial-block']; 25199 options.partial = true; 25200 if (options.ids) { 25201 options.data.contextPath = options.ids[0] || options.data.contextPath; 25202 } 25203 25204 var partialBlock = undefined; 25205 if (options.fn && options.fn !== noop) { 25206 (function () { 25207 options.data = _base.createFrame(options.data); 25208 // Wrapper function to get access to currentPartialBlock from the closure 25209 var fn = options.fn; 25210 partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) { 25211 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 25212 25213 // Restore the partial-block from the closure for the execution of the block 25214 // i.e. the part inside the block of the partial call. 25215 options.data = _base.createFrame(options.data); 25216 options.data['partial-block'] = currentPartialBlock; 25217 return fn(context, options); 25218 }; 25219 if (fn.partials) { 25220 options.partials = Utils.extend({}, options.partials, fn.partials); 25221 } 25222 })(); 25223 } 25224 25225 if (partial === undefined && partialBlock) { 25226 partial = partialBlock; 25227 } 25228 25229 if (partial === undefined) { 25230 throw new _exception2['default']('The partial ' + options.name + ' could not be found'); 25231 } else if (partial instanceof Function) { 25232 return partial(context, options); 25233 } 25234 } 25235 25236 function noop() { 25237 return ''; 25238 } 25239 25240 function initData(context, data) { 25241 if (!data || !('root' in data)) { 25242 data = data ? _base.createFrame(data) : {}; 25243 data.root = context; 25244 } 25245 return data; 25246 } 25247 25248 function executeDecorators(fn, prog, container, depths, data, blockParams) { 25249 if (fn.decorator) { 25250 var props = {}; 25251 prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); 25252 Utils.extend(prog, props); 25253 } 25254 return prog; 25255 } 25256 25257/***/ }), 25258/* 23 */ 25259/***/ (function(module, exports, __webpack_require__) { 25260 25261 module.exports = { "default": __webpack_require__(24), __esModule: true }; 25262 25263/***/ }), 25264/* 24 */ 25265/***/ (function(module, exports, __webpack_require__) { 25266 25267 __webpack_require__(25); 25268 module.exports = __webpack_require__(30).Object.seal; 25269 25270/***/ }), 25271/* 25 */ 25272/***/ (function(module, exports, __webpack_require__) { 25273 25274 // 19.1.2.17 Object.seal(O) 25275 var isObject = __webpack_require__(26); 25276 25277 __webpack_require__(27)('seal', function($seal){ 25278 return function seal(it){ 25279 return $seal && isObject(it) ? $seal(it) : it; 25280 }; 25281 }); 25282 25283/***/ }), 25284/* 26 */ 25285/***/ (function(module, exports) { 25286 25287 module.exports = function(it){ 25288 return typeof it === 'object' ? it !== null : typeof it === 'function'; 25289 }; 25290 25291/***/ }), 25292/* 27 */ 25293/***/ (function(module, exports, __webpack_require__) { 25294 25295 // most Object methods by ES6 should accept primitives 25296 var $export = __webpack_require__(28) 25297 , core = __webpack_require__(30) 25298 , fails = __webpack_require__(33); 25299 module.exports = function(KEY, exec){ 25300 var fn = (core.Object || {})[KEY] || Object[KEY] 25301 , exp = {}; 25302 exp[KEY] = exec(fn); 25303 $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp); 25304 }; 25305 25306/***/ }), 25307/* 28 */ 25308/***/ (function(module, exports, __webpack_require__) { 25309 25310 var global = __webpack_require__(29) 25311 , core = __webpack_require__(30) 25312 , ctx = __webpack_require__(31) 25313 , PROTOTYPE = 'prototype'; 25314 25315 var $export = function(type, name, source){ 25316 var IS_FORCED = type & $export.F 25317 , IS_GLOBAL = type & $export.G 25318 , IS_STATIC = type & $export.S 25319 , IS_PROTO = type & $export.P 25320 , IS_BIND = type & $export.B 25321 , IS_WRAP = type & $export.W 25322 , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) 25323 , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] 25324 , key, own, out; 25325 if(IS_GLOBAL)source = name; 25326 for(key in source){ 25327 // contains in native 25328 own = !IS_FORCED && target && key in target; 25329 if(own && key in exports)continue; 25330 // export native or passed 25331 out = own ? target[key] : source[key]; 25332 // prevent global pollution for namespaces 25333 exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] 25334 // bind timers to global for call from export context 25335 : IS_BIND && own ? ctx(out, global) 25336 // wrap global constructors for prevent change them in library 25337 : IS_WRAP && target[key] == out ? (function(C){ 25338 var F = function(param){ 25339 return this instanceof C ? new C(param) : C(param); 25340 }; 25341 F[PROTOTYPE] = C[PROTOTYPE]; 25342 return F; 25343 // make static versions for prototype methods 25344 })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; 25345 if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out; 25346 } 25347 }; 25348 // type bitmap 25349 $export.F = 1; // forced 25350 $export.G = 2; // global 25351 $export.S = 4; // static 25352 $export.P = 8; // proto 25353 $export.B = 16; // bind 25354 $export.W = 32; // wrap 25355 module.exports = $export; 25356 25357/***/ }), 25358/* 29 */ 25359/***/ (function(module, exports) { 25360 25361 // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 25362 var global = module.exports = typeof window != 'undefined' && window.Math == Math 25363 ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); 25364 if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef 25365 25366/***/ }), 25367/* 30 */ 25368/***/ (function(module, exports) { 25369 25370 var core = module.exports = {version: '1.2.6'}; 25371 if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef 25372 25373/***/ }), 25374/* 31 */ 25375/***/ (function(module, exports, __webpack_require__) { 25376 25377 // optional / simple context binding 25378 var aFunction = __webpack_require__(32); 25379 module.exports = function(fn, that, length){ 25380 aFunction(fn); 25381 if(that === undefined)return fn; 25382 switch(length){ 25383 case 1: return function(a){ 25384 return fn.call(that, a); 25385 }; 25386 case 2: return function(a, b){ 25387 return fn.call(that, a, b); 25388 }; 25389 case 3: return function(a, b, c){ 25390 return fn.call(that, a, b, c); 25391 }; 25392 } 25393 return function(/* ...args */){ 25394 return fn.apply(that, arguments); 25395 }; 25396 }; 25397 25398/***/ }), 25399/* 32 */ 25400/***/ (function(module, exports) { 25401 25402 module.exports = function(it){ 25403 if(typeof it != 'function')throw TypeError(it + ' is not a function!'); 25404 return it; 25405 }; 25406 25407/***/ }), 25408/* 33 */ 25409/***/ (function(module, exports) { 25410 25411 module.exports = function(exec){ 25412 try { 25413 return !!exec(); 25414 } catch(e){ 25415 return true; 25416 } 25417 }; 25418 25419/***/ }), 25420/* 34 */ 25421/***/ (function(module, exports) { 25422 25423 /* WEBPACK VAR INJECTION */(function(global) {/* global window */ 25424 'use strict'; 25425 25426 exports.__esModule = true; 25427 25428 exports['default'] = function (Handlebars) { 25429 /* istanbul ignore next */ 25430 var root = typeof global !== 'undefined' ? global : window, 25431 $Handlebars = root.Handlebars; 25432 /* istanbul ignore next */ 25433 Handlebars.noConflict = function () { 25434 if (root.Handlebars === Handlebars) { 25435 root.Handlebars = $Handlebars; 25436 } 25437 return Handlebars; 25438 }; 25439 }; 25440 25441 module.exports = exports['default']; 25442 /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) 25443 25444/***/ }), 25445/* 35 */ 25446/***/ (function(module, exports) { 25447 25448 'use strict'; 25449 25450 exports.__esModule = true; 25451 var AST = { 25452 // Public API used to evaluate derived attributes regarding AST nodes 25453 helpers: { 25454 // a mustache is definitely a helper if: 25455 // * it is an eligible helper, and 25456 // * it has at least one parameter or hash segment 25457 helperExpression: function helperExpression(node) { 25458 return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); 25459 }, 25460 25461 scopedId: function scopedId(path) { 25462 return (/^\.|this\b/.test(path.original) 25463 ); 25464 }, 25465 25466 // an ID is simple if it only has one part, and that part is not 25467 // `..` or `this`. 25468 simpleId: function simpleId(path) { 25469 return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; 25470 } 25471 } 25472 }; 25473 25474 // Must be exported as an object rather than the root of the module as the jison lexer 25475 // must modify the object to operate properly. 25476 exports['default'] = AST; 25477 module.exports = exports['default']; 25478 25479/***/ }), 25480/* 36 */ 25481/***/ (function(module, exports, __webpack_require__) { 25482 25483 'use strict'; 25484 25485 var _interopRequireDefault = __webpack_require__(1)['default']; 25486 25487 var _interopRequireWildcard = __webpack_require__(3)['default']; 25488 25489 exports.__esModule = true; 25490 exports.parse = parse; 25491 25492 var _parser = __webpack_require__(37); 25493 25494 var _parser2 = _interopRequireDefault(_parser); 25495 25496 var _whitespaceControl = __webpack_require__(38); 25497 25498 var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl); 25499 25500 var _helpers = __webpack_require__(40); 25501 25502 var Helpers = _interopRequireWildcard(_helpers); 25503 25504 var _utils = __webpack_require__(5); 25505 25506 exports.parser = _parser2['default']; 25507 25508 var yy = {}; 25509 _utils.extend(yy, Helpers); 25510 25511 function parse(input, options) { 25512 // Just return if an already-compiled AST was passed in. 25513 if (input.type === 'Program') { 25514 return input; 25515 } 25516 25517 _parser2['default'].yy = yy; 25518 25519 // Altering the shared object here, but this is ok as parser is a sync operation 25520 yy.locInfo = function (locInfo) { 25521 return new yy.SourceLocation(options && options.srcName, locInfo); 25522 }; 25523 25524 var strip = new _whitespaceControl2['default'](options); 25525 return strip.accept(_parser2['default'].parse(input)); 25526 } 25527 25528/***/ }), 25529/* 37 */ 25530/***/ (function(module, exports) { 25531 25532 // File ignored in coverage tests via setting in .istanbul.yml 25533 /* Jison generated parser */ 25534 "use strict"; 25535 25536 exports.__esModule = true; 25537 var handlebars = (function () { 25538 var parser = { trace: function trace() {}, 25539 yy: {}, 25540 symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition_plus0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, 25541 terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT",
vendor: 26,541 bytes, lines 25541-25797
2554118: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, 25542 productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 1], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], 25543 performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$ 25544 /*``*/) { 25545 25546 var $0 = $$.length - 1; 25547 switch (yystate) { 25548 case 1: 25549 return $$[$0 - 1]; 25550 break; 25551 case 2: 25552 this.$ = yy.prepareProgram($$[$0]); 25553 break; 25554 case 3: 25555 this.$ = $$[$0]; 25556 break; 25557 case 4: 25558 this.$ = $$[$0]; 25559 break; 25560 case 5: 25561 this.$ = $$[$0]; 25562 break; 25563 case 6: 25564 this.$ = $$[$0]; 25565 break; 25566 case 7: 25567 this.$ = $$[$0]; 25568 break; 25569 case 8: 25570 this.$ = $$[$0]; 25571 break; 25572 case 9: 25573 this.$ = { 25574 type: 'CommentStatement', 25575 value: yy.stripComment($$[$0]), 25576 strip: yy.stripFlags($$[$0], $$[$0]), 25577 loc: yy.locInfo(this._$) 25578 }; 25579 25580 break; 25581 case 10: 25582 this.$ = { 25583 type: 'ContentStatement', 25584 original: $$[$0], 25585 value: $$[$0], 25586 loc: yy.locInfo(this._$) 25587 }; 25588 25589 break; 25590 case 11: 25591 this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); 25592 break; 25593 case 12: 25594 this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; 25595 break; 25596 case 13: 25597 this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); 25598 break; 25599 case 14: 25600 this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); 25601 break; 25602 case 15: 25603 this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; 25604 break; 25605 case 16: 25606 this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; 25607 break; 25608 case 17: 25609 this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; 25610 break; 25611 case 18: 25612 this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; 25613 break; 25614 case 19: 25615 var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), 25616 program = yy.prepareProgram([inverse], $$[$0 - 1].loc); 25617 program.chained = true; 25618 25619 this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; 25620 25621 break; 25622 case 20: 25623 this.$ = $$[$0]; 25624 break; 25625 case 21: 25626 this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; 25627 break; 25628 case 22: 25629 this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); 25630 break; 25631 case 23: 25632 this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); 25633 break; 25634 case 24: 25635 this.$ = { 25636 type: 'PartialStatement', 25637 name: $$[$0 - 3], 25638 params: $$[$0 - 2], 25639 hash: $$[$0 - 1], 25640 indent: '', 25641 strip: yy.stripFlags($$[$0 - 4], $$[$0]), 25642 loc: yy.locInfo(this._$) 25643 }; 25644 25645 break; 25646 case 25: 25647 this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); 25648 break; 25649 case 26: 25650 this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; 25651 break; 25652 case 27: 25653 this.$ = $$[$0]; 25654 break; 25655 case 28: 25656 this.$ = $$[$0]; 25657 break; 25658 case 29: 25659 this.$ = { 25660 type: 'SubExpression', 25661 path: $$[$0 - 3], 25662 params: $$[$0 - 2], 25663 hash: $$[$0 - 1], 25664 loc: yy.locInfo(this._$) 25665 }; 25666 25667 break; 25668 case 30: 25669 this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; 25670 break; 25671 case 31: 25672 this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; 25673 break; 25674 case 32: 25675 this.$ = yy.id($$[$0 - 1]); 25676 break; 25677 case 33: 25678 this.$ = $$[$0]; 25679 break; 25680 case 34: 25681 this.$ = $$[$0]; 25682 break; 25683 case 35: 25684 this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; 25685 break; 25686 case 36: 25687 this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; 25688 break; 25689 case 37: 25690 this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; 25691 break; 25692 case 38: 25693 this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; 25694 break; 25695 case 39: 25696 this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; 25697 break; 25698 case 40: 25699 this.$ = $$[$0]; 25700 break; 25701 case 41: 25702 this.$ = $$[$0]; 25703 break; 25704 case 42: 25705 this.$ = yy.preparePath(true, $$[$0], this._$); 25706 break; 25707 case 43: 25708 this.$ = yy.preparePath(false, $$[$0], this._$); 25709 break; 25710 case 44: 25711 $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; 25712 break; 25713 case 45: 25714 this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; 25715 break; 25716 case 46: 25717 this.$ = []; 25718 break; 25719 case 47: 25720 $$[$0 - 1].push($$[$0]); 25721 break; 25722 case 48: 25723 this.$ = [$$[$0]]; 25724 break; 25725 case 49: 25726 $$[$0 - 1].push($$[$0]); 25727 break; 25728 case 50: 25729 this.$ = []; 25730 break; 25731 case 51: 25732 $$[$0 - 1].push($$[$0]); 25733 break; 25734 case 58: 25735 this.$ = []; 25736 break; 25737 case 59: 25738 $$[$0 - 1].push($$[$0]); 25739 break; 25740 case 64: 25741 this.$ = []; 25742 break; 25743 case 65: 25744 $$[$0 - 1].push($$[$0]); 25745 break; 25746 case 70: 25747 this.$ = []; 25748 break; 25749 case 71: 25750 $$[$0 - 1].push($$[$0]); 25751 break; 25752 case 78: 25753 this.$ = []; 25754 break; 25755 case 79: 25756 $$[$0 - 1].push($$[$0]); 25757 break; 25758 case 82: 25759 this.$ = []; 25760 break; 25761 case 83: 25762 $$[$0 - 1].push($$[$0]); 25763 break; 25764 case 86: 25765 this.$ = []; 25766 break; 25767 case 87: 25768 $$[$0 - 1].push($$[$0]); 25769 break; 25770 case 90: 25771 this.$ = []; 25772 break; 25773 case 91: 25774 $$[$0 - 1].push($$[$0]); 25775 break; 25776 case 94: 25777 this.$ = []; 25778 break; 25779 case 95: 25780 $$[$0 - 1].push($$[$0]); 25781 break; 25782 case 98: 25783 this.$ = [$$[$0]]; 25784 break; 25785 case 99: 25786 $$[$0 - 1].push($$[$0]); 25787 break; 25788 case 100: 25789 this.$ = [$$[$0]]; 25790 break; 25791 case 101: 25792 $$[$0 - 1].push($$[$0]); 25793 break; 25794 } 25795 }, 25796 table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 13: 40, 15: [1, 20], 17: 39 }, { 20: 42, 56: 41, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 45, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 48, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 42, 56: 49, 64: 43, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 50, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 51] }, { 72: [1, 35], 86: 52 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 53, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 54, 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 55, 47: [2, 54] }, { 28: 60, 43: 61, 44: [1, 59], 47: [2, 56] }, { 13: 63, 15: [1, 20], 18: [1, 62] }, { 15: [2, 48], 18: [2, 48] }, { 33: [2, 86], 57: 64, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 65, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 66, 47: [1, 67] }, { 30: 68, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 69, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 70, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 71, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 75, 33: [2, 80], 50: 72, 63: 73, 64: 76, 65: [1, 44], 69: 74, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 80] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 51] }, { 20: 75, 53: 81, 54: [2, 84], 63: 82, 64: 76, 65: [1, 44], 69: 83, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 84, 47: [1, 67] }, { 47: [2, 55] }, { 4: 85, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 86, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 87, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 88, 47: [1, 67] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 75, 33: [2, 88], 58: 89, 63: 90, 64: 76, 65: [1, 44], 69: 91, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 92, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 93, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 31: 94, 33: [2, 60], 63: 95, 64: 76, 65: [1, 44], 69: 96, 70: 77, 71: 78, 72: [1, 79], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 66], 36: 97, 63: 98, 64: 76, 65: [1, 44], 69: 99, 70: 77, 71: 78, 72: [1, 79], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 22: 100, 23: [2, 52], 63: 101, 64: 76, 65: [1, 44], 69: 102, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 75, 33: [2, 92], 62: 103, 63: 104, 64: 76, 65: [1, 44], 69: 105, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 106] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 107, 72: [1, 108], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 109], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 110] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 56, 39: [1, 58], 43: 57, 44: [1, 59], 45: 112, 46: 111, 47: [2, 76] }, { 33: [2, 70], 40: 113, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 114] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 75, 63: 116, 64: 76, 65: [1, 44], 67: 115, 68: [2, 96], 69: 117, 70: 77, 71: 78, 72: [1, 79], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 118] }, { 32: 119, 33: [2, 62], 74: 120, 75: [1, 121] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 122, 74: 123, 75: [1, 121] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 124] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 125] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 109] }, { 20: 75, 63: 126, 64: 76, 65: [1, 44], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 75, 33: [2, 72], 41: 127, 63: 128, 64: 76, 65: [1, 44], 69: 129, 70: 77, 71: 78, 72: [1, 79], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 130] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 131] }, { 33: [2, 63] }, { 72: [1, 133], 76: 132 }, { 33: [1, 134] }, { 33: [2, 69] }, { 15: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 135, 74: 136, 75: [1, 121] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 138], 77: [1, 137] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 139] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], 25797 defaultActions: { 4: [2, 1], 55: [2, 55], 57: [2, 20], 61: [2, 57], 74: [2, 81], 83: [2, 85], 87: [2, 18], 91: [2, 89], 102: [2, 53], 105: [2, 93], 111: [2, 19], 112: [2, 77], 117: [2, 97
25797], 120: [2, 63], 123: [2, 69], 124: [2, 12], 136: [2, 75], 137
vendor: 13,423 bytes, lines 25797-26081
25797: [2, 32] }, 25798 parseError: function parseError(str, hash) { 25799 throw new Error(str); 25800 }, 25801 parse: function parse(input) { 25802 var self = this, 25803 stack = [0], 25804 vstack = [null], 25805 lstack = [], 25806 table = this.table, 25807 yytext = "", 25808 yylineno = 0, 25809 yyleng = 0, 25810 recovering = 0, 25811 TERROR = 2, 25812 EOF = 1; 25813 this.lexer.setInput(input); 25814 this.lexer.yy = this.yy; 25815 this.yy.lexer = this.lexer; 25816 this.yy.parser = this; 25817 if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; 25818 var yyloc = this.lexer.yylloc; 25819 lstack.push(yyloc); 25820 var ranges = this.lexer.options && this.lexer.options.ranges; 25821 if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; 25822 function popStack(n) { 25823 stack.length = stack.length - 2 * n; 25824 vstack.length = vstack.length - n; 25825 lstack.length = lstack.length - n; 25826 } 25827 function lex() { 25828 var token; 25829 token = self.lexer.lex() || 1; 25830 if (typeof token !== "number") { 25831 token = self.symbols_[token] || token; 25832 } 25833 return token; 25834 } 25835 var symbol, 25836 preErrorSymbol, 25837 state, 25838 action, 25839 a, 25840 r, 25841 yyval = {}, 25842 p, 25843 len, 25844 newState, 25845 expected; 25846 while (true) { 25847 state = stack[stack.length - 1]; 25848 if (this.defaultActions[state]) { 25849 action = this.defaultActions[state]; 25850 } else { 25851 if (symbol === null || typeof symbol == "undefined") { 25852 symbol = lex(); 25853 } 25854 action = table[state] && table[state][symbol]; 25855 } 25856 if (typeof action === "undefined" || !action.length || !action[0]) { 25857 var errStr = ""; 25858 if (!recovering) { 25859 expected = []; 25860 for (p in table[state]) if (this.terminals_[p] && p > 2) { 25861 expected.push("'" + this.terminals_[p] + "'"); 25862 } 25863 if (this.lexer.showPosition) { 25864 errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; 25865 } else { 25866 errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); 25867 } 25868 this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); 25869 } 25870 } 25871 if (action[0] instanceof Array && action.length > 1) { 25872 throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); 25873 } 25874 switch (action[0]) { 25875 case 1: 25876 stack.push(symbol); 25877 vstack.push(this.lexer.yytext); 25878 lstack.push(this.lexer.yylloc); 25879 stack.push(action[1]); 25880 symbol = null; 25881 if (!preErrorSymbol) { 25882 yyleng = this.lexer.yyleng; 25883 yytext = this.lexer.yytext; 25884 yylineno = this.lexer.yylineno; 25885 yyloc = this.lexer.yylloc; 25886 if (recovering > 0) recovering--; 25887 } else { 25888 symbol = preErrorSymbol; 25889 preErrorSymbol = null; 25890 } 25891 break; 25892 case 2: 25893 len = this.productions_[action[1]][1]; 25894 yyval.$ = vstack[vstack.length - len]; 25895 yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; 25896 if (ranges) { 25897 yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; 25898 } 25899 r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); 25900 if (typeof r !== "undefined") { 25901 return r; 25902 } 25903 if (len) { 25904 stack = stack.slice(0, -1 * len * 2); 25905 vstack = vstack.slice(0, -1 * len); 25906 lstack = lstack.slice(0, -1 * len); 25907 } 25908 stack.push(this.productions_[action[1]][0]); 25909 vstack.push(yyval.$); 25910 lstack.push(yyval._$); 25911 newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; 25912 stack.push(newState); 25913 break; 25914 case 3: 25915 return true; 25916 } 25917 } 25918 return true; 25919 } 25920 }; 25921 /* Jison generated lexer */ 25922 var lexer = (function () { 25923 var lexer = { EOF: 1, 25924 parseError: function parseError(str, hash) { 25925 if (this.yy.parser) { 25926 this.yy.parser.parseError(str, hash); 25927 } else { 25928 throw new Error(str); 25929 } 25930 }, 25931 setInput: function setInput(input) { 25932 this._input = input; 25933 this._more = this._less = this.done = false; 25934 this.yylineno = this.yyleng = 0; 25935 this.yytext = this.matched = this.match = ''; 25936 this.conditionStack = ['INITIAL']; 25937 this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; 25938 if (this.options.ranges) this.yylloc.range = [0, 0]; 25939 this.offset = 0; 25940 return this; 25941 }, 25942 input: function input() { 25943 var ch = this._input[0]; 25944 this.yytext += ch; 25945 this.yyleng++; 25946 this.offset++; 25947 this.match += ch; 25948 this.matched += ch; 25949 var lines = ch.match(/(?:\r\n?|\n).*/g); 25950 if (lines) { 25951 this.yylineno++; 25952 this.yylloc.last_line++; 25953 } else { 25954 this.yylloc.last_column++; 25955 } 25956 if (this.options.ranges) this.yylloc.range[1]++; 25957 25958 this._input = this._input.slice(1); 25959 return ch; 25960 }, 25961 unput: function unput(ch) { 25962 var len = ch.length; 25963 var lines = ch.split(/(?:\r\n?|\n)/g); 25964 25965 this._input = ch + this._input; 25966 this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); 25967 //this.yyleng -= len; 25968 this.offset -= len; 25969 var oldLines = this.match.split(/(?:\r\n?|\n)/g); 25970 this.match = this.match.substr(0, this.match.length - 1); 25971 this.matched = this.matched.substr(0, this.matched.length - 1); 25972 25973 if (lines.length - 1) this.yylineno -= lines.length - 1; 25974 var r = this.yylloc.range; 25975 25976 this.yylloc = { first_line: this.yylloc.first_line, 25977 last_line: this.yylineno + 1, 25978 first_column: this.yylloc.first_column, 25979 last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len 25980 }; 25981 25982 if (this.options.ranges) { 25983 this.yylloc.range = [r[0], r[0] + this.yyleng - len]; 25984 } 25985 return this; 25986 }, 25987 more: function more() { 25988 this._more = true; 25989 return this; 25990 }, 25991 less: function less(n) { 25992 this.unput(this.match.slice(n)); 25993 }, 25994 pastInput: function pastInput() { 25995 var past = this.matched.substr(0, this.matched.length - this.match.length); 25996 return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); 25997 }, 25998 upcomingInput: function upcomingInput() { 25999 var next = this.match; 26000 if (next.length < 20) { 26001 next += this._input.substr(0, 20 - next.length); 26002 } 26003 return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); 26004 }, 26005 showPosition: function showPosition() { 26006 var pre = this.pastInput(); 26007 var c = new Array(pre.length + 1).join("-"); 26008 return pre + this.upcomingInput() + "\n" + c + "^"; 26009 }, 26010 next: function next() { 26011 if (this.done) { 26012 return this.EOF; 26013 } 26014 if (!this._input) this.done = true; 26015 26016 var token, match, tempMatch, index, col, lines; 26017 if (!this._more) { 26018 this.yytext = ''; 26019 this.match = ''; 26020 } 26021 var rules = this._currentRules(); 26022 for (var i = 0; i < rules.length; i++) { 26023 tempMatch = this._input.match(this.rules[rules[i]]); 26024 if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { 26025 match = tempMatch; 26026 index = i; 26027 if (!this.options.flex) break; 26028 } 26029 } 26030 if (match) { 26031 lines = match[0].match(/(?:\r\n?|\n).*/g); 26032 if (lines) this.yylineno += lines.length; 26033 this.yylloc = { first_line: this.yylloc.last_line, 26034 last_line: this.yylineno + 1, 26035 first_column: this.yylloc.last_column, 26036 last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; 26037 this.yytext += match[0]; 26038 this.match += match[0]; 26039 this.matches = match; 26040 this.yyleng = this.yytext.length; 26041 if (this.options.ranges) { 26042 this.yylloc.range = [this.offset, this.offset += this.yyleng]; 26043 } 26044 this._more = false; 26045 this._input = this._input.slice(match[0].length); 26046 this.matched += match[0]; 26047 token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); 26048 if (this.done && this._input) this.done = false; 26049 if (token) return token;else return; 26050 } 26051 if (this._input === "") { 26052 return this.EOF; 26053 } else { 26054 return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); 26055 } 26056 }, 26057 lex: function lex() { 26058 var r = this.next(); 26059 if (typeof r !== 'undefined') { 26060 return r; 26061 } else { 26062 return this.lex(); 26063 } 26064 }, 26065 begin: function begin(condition) { 26066 this.conditionStack.push(condition); 26067 }, 26068 popState: function popState() { 26069 return this.conditionStack.pop(); 26070 }, 26071 _currentRules: function _currentRules() { 26072 return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; 26073 }, 26074 topState: function topState() { 26075 return this.conditionStack[this.conditionStack.length - 2]; 26076 }, 26077 pushState: function begin(condition) { 26078 this.begin(condition); 26079 } }; 26080 lexer.options = {}; 26081 lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START
vendor: 7,148 bytes, lines 26081-26261
26081 26082 /*``*/) { 26083 26084 function strip(start, end) { 26085 return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng - end); 26086 } 26087 26088 var YYSTATE = YY_START; 26089 switch ($avoiding_name_collisions) { 26090 case 0: 26091 if (yy_.yytext.slice(-2) === "\\\\") { 26092 strip(0, 1); 26093 this.begin("mu"); 26094 } else if (yy_.yytext.slice(-1) === "\\") { 26095 strip(0, 1); 26096 this.begin("emu"); 26097 } else { 26098 this.begin("mu"); 26099 } 26100 if (yy_.yytext) return 15; 26101 26102 break; 26103 case 1: 26104 return 15; 26105 break; 26106 case 2: 26107 this.popState(); 26108 return 15; 26109 26110 break; 26111 case 3: 26112 this.begin('raw');return 15; 26113 break; 26114 case 4: 26115 this.popState(); 26116 // Should be using `this.topState()` below, but it currently 26117 // returns the second top instead of the first top. Opened an 26118 // issue about it at https://github.com/zaach/jison/issues/291 26119 if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { 26120 return 15; 26121 } else { 26122 yy_.yytext = yy_.yytext.substr(5, yy_.yyleng - 9); 26123 return 'END_RAW_BLOCK'; 26124 } 26125 26126 break; 26127 case 5: 26128 return 15; 26129 break; 26130 case 6: 26131 this.popState(); 26132 return 14; 26133 26134 break; 26135 case 7: 26136 return 65; 26137 break; 26138 case 8: 26139 return 68; 26140 break; 26141 case 9: 26142 return 19; 26143 break; 26144 case 10: 26145 this.popState(); 26146 this.begin('raw'); 26147 return 23; 26148 26149 break; 26150 case 11: 26151 return 55; 26152 break; 26153 case 12: 26154 return 60; 26155 break; 26156 case 13: 26157 return 29; 26158 break; 26159 case 14: 26160 return 47; 26161 break; 26162 case 15: 26163 this.popState();return 44; 26164 break; 26165 case 16: 26166 this.popState();return 44; 26167 break; 26168 case 17: 26169 return 34; 26170 break; 26171 case 18: 26172 return 39; 26173 break; 26174 case 19: 26175 return 51; 26176 break; 26177 case 20: 26178 return 48; 26179 break; 26180 case 21: 26181 this.unput(yy_.yytext); 26182 this.popState(); 26183 this.begin('com'); 26184 26185 break; 26186 case 22: 26187 this.popState(); 26188 return 14; 26189 26190 break; 26191 case 23: 26192 return 48; 26193 break; 26194 case 24: 26195 return 73; 26196 break; 26197 case 25: 26198 return 72; 26199 break; 26200 case 26: 26201 return 72; 26202 break; 26203 case 27: 26204 return 87; 26205 break; 26206 case 28: 26207 // ignore whitespace 26208 break; 26209 case 29: 26210 this.popState();return 54; 26211 break; 26212 case 30: 26213 this.popState();return 33; 26214 break; 26215 case 31: 26216 yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; 26217 break; 26218 case 32: 26219 yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; 26220 break; 26221 case 33: 26222 return 85; 26223 break; 26224 case 34: 26225 return 82; 26226 break; 26227 case 35: 26228 return 82; 26229 break; 26230 case 36: 26231 return 83; 26232 break; 26233 case 37: 26234 return 84; 26235 break; 26236 case 38: 26237 return 81; 26238 break; 26239 case 39: 26240 return 75; 26241 break; 26242 case 40: 26243 return 77; 26244 break; 26245 case 41: 26246 return 72; 26247 break; 26248 case 42: 26249 yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; 26250 break; 26251 case 43: 26252 return 'INVALID'; 26253 break; 26254 case 44: 26255 return 5; 26256 break; 26257 } 26258 }; 26259 lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]*?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; 26260 lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; 26261 return lexer;
vendor: 12,193 bytes, lines 26262-26686
26262 })(); 26263 parser.lexer = lexer; 26264 function Parser() { 26265 this.yy = {}; 26266 }Parser.prototype = parser;parser.Parser = Parser; 26267 return new Parser(); 26268 })();exports["default"] = handlebars; 26269 module.exports = exports["default"]; 26270 26271/***/ }), 26272/* 38 */ 26273/***/ (function(module, exports, __webpack_require__) { 26274 26275 'use strict'; 26276 26277 var _interopRequireDefault = __webpack_require__(1)['default']; 26278 26279 exports.__esModule = true; 26280 26281 var _visitor = __webpack_require__(39); 26282 26283 var _visitor2 = _interopRequireDefault(_visitor); 26284 26285 function WhitespaceControl() { 26286 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 26287 26288 this.options = options; 26289 } 26290 WhitespaceControl.prototype = new _visitor2['default'](); 26291 26292 WhitespaceControl.prototype.Program = function (program) { 26293 var doStandalone = !this.options.ignoreStandalone; 26294 26295 var isRoot = !this.isRootSeen; 26296 this.isRootSeen = true; 26297 26298 var body = program.body; 26299 for (var i = 0, l = body.length; i < l; i++) { 26300 var current = body[i], 26301 strip = this.accept(current); 26302 26303 if (!strip) { 26304 continue; 26305 } 26306 26307 var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), 26308 _isNextWhitespace = isNextWhitespace(body, i, isRoot), 26309 openStandalone = strip.openStandalone && _isPrevWhitespace, 26310 closeStandalone = strip.closeStandalone && _isNextWhitespace, 26311 inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; 26312 26313 if (strip.close) { 26314 omitRight(body, i, true); 26315 } 26316 if (strip.open) { 26317 omitLeft(body, i, true); 26318 } 26319 26320 if (doStandalone && inlineStandalone) { 26321 omitRight(body, i); 26322 26323 if (omitLeft(body, i)) { 26324 // If we are on a standalone node, save the indent info for partials 26325 if (current.type === 'PartialStatement') { 26326 // Pull out the whitespace from the final line 26327 current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; 26328 } 26329 } 26330 } 26331 if (doStandalone && openStandalone) { 26332 omitRight((current.program || current.inverse).body); 26333 26334 // Strip out the previous content node if it's whitespace only 26335 omitLeft(body, i); 26336 } 26337 if (doStandalone && closeStandalone) { 26338 // Always strip the next node 26339 omitRight(body, i); 26340 26341 omitLeft((current.inverse || current.program).body); 26342 } 26343 } 26344 26345 return program; 26346 }; 26347 26348 WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { 26349 this.accept(block.program); 26350 this.accept(block.inverse); 26351 26352 // Find the inverse program that is involed with whitespace stripping. 26353 var program = block.program || block.inverse, 26354 inverse = block.program && block.inverse, 26355 firstInverse = inverse, 26356 lastInverse = inverse; 26357 26358 if (inverse && inverse.chained) { 26359 firstInverse = inverse.body[0].program; 26360 26361 // Walk the inverse chain to find the last inverse that is actually in the chain. 26362 while (lastInverse.chained) { 26363 lastInverse = lastInverse.body[lastInverse.body.length - 1].program; 26364 } 26365 } 26366 26367 var strip = { 26368 open: block.openStrip.open, 26369 close: block.closeStrip.close, 26370 26371 // Determine the standalone candiacy. Basically flag our content as being possibly standalone 26372 // so our parent can determine if we actually are standalone 26373 openStandalone: isNextWhitespace(program.body), 26374 closeStandalone: isPrevWhitespace((firstInverse || program).body) 26375 }; 26376 26377 if (block.openStrip.close) { 26378 omitRight(program.body, null, true); 26379 } 26380 26381 if (inverse) { 26382 var inverseStrip = block.inverseStrip; 26383 26384 if (inverseStrip.open) { 26385 omitLeft(program.body, null, true); 26386 } 26387 26388 if (inverseStrip.close) { 26389 omitRight(firstInverse.body, null, true); 26390 } 26391 if (block.closeStrip.open) { 26392 omitLeft(lastInverse.body, null, true); 26393 } 26394 26395 // Find standalone else statments 26396 if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { 26397 omitLeft(program.body); 26398 omitRight(firstInverse.body); 26399 } 26400 } else if (block.closeStrip.open) { 26401 omitLeft(program.body, null, true); 26402 } 26403 26404 return strip; 26405 }; 26406 26407 WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { 26408 return mustache.strip; 26409 }; 26410 26411 WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { 26412 /* istanbul ignore next */ 26413 var strip = node.strip || {}; 26414 return { 26415 inlineStandalone: true, 26416 open: strip.open, 26417 close: strip.close 26418 }; 26419 }; 26420 26421 function isPrevWhitespace(body, i, isRoot) { 26422 if (i === undefined) { 26423 i = body.length; 26424 } 26425 26426 // Nodes that end with newlines are considered whitespace (but are special 26427 // cased for strip operations) 26428 var prev = body[i - 1], 26429 sibling = body[i - 2]; 26430 if (!prev) { 26431 return isRoot; 26432 } 26433 26434 if (prev.type === 'ContentStatement') { 26435 return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); 26436 } 26437 } 26438 function isNextWhitespace(body, i, isRoot) { 26439 if (i === undefined) { 26440 i = -1; 26441 } 26442 26443 var next = body[i + 1], 26444 sibling = body[i + 2]; 26445 if (!next) { 26446 return isRoot; 26447 } 26448 26449 if (next.type === 'ContentStatement') { 26450 return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); 26451 } 26452 } 26453 26454 // Marks the node to the right of the position as omitted. 26455 // I.e. {{foo}}' ' will mark the ' ' node as omitted. 26456 // 26457 // If i is undefined, then the first child will be marked as such. 26458 // 26459 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace 26460 // content is met. 26461 function omitRight(body, i, multiple) { 26462 var current = body[i == null ? 0 : i + 1]; 26463 if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { 26464 return; 26465 } 26466 26467 var original = current.value; 26468 current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); 26469 current.rightStripped = current.value !== original; 26470 } 26471 26472 // Marks the node to the left of the position as omitted. 26473 // I.e. ' '{{foo}} will mark the ' ' node as omitted. 26474 // 26475 // If i is undefined then the last child will be marked as such. 26476 // 26477 // If mulitple is truthy then all whitespace will be stripped out until non-whitespace 26478 // content is met. 26479 function omitLeft(body, i, multiple) { 26480 var current = body[i == null ? body.length - 1 : i - 1]; 26481 if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { 26482 return; 26483 } 26484 26485 // We omit the last node if it's whitespace only and not preceeded by a non-content node. 26486 var original = current.value; 26487 current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); 26488 current.leftStripped = current.value !== original; 26489 return current.leftStripped; 26490 } 26491 26492 exports['default'] = WhitespaceControl; 26493 module.exports = exports['default']; 26494 26495/***/ }), 26496/* 39 */ 26497/***/ (function(module, exports, __webpack_require__) { 26498 26499 'use strict'; 26500 26501 var _interopRequireDefault = __webpack_require__(1)['default']; 26502 26503 exports.__esModule = true; 26504 26505 var _exception = __webpack_require__(6); 26506 26507 var _exception2 = _interopRequireDefault(_exception); 26508 26509 function Visitor() { 26510 this.parents = []; 26511 } 26512 26513 Visitor.prototype = { 26514 constructor: Visitor, 26515 mutating: false, 26516 26517 // Visits a given value. If mutating, will replace the value if necessary. 26518 acceptKey: function acceptKey(node, name) { 26519 var value = this.accept(node[name]); 26520 if (this.mutating) { 26521 // Hacky sanity check: This may have a few false positives for type for the helper 26522 // methods but will generally do the right thing without a lot of overhead. 26523 if (value && !Visitor.prototype[value.type]) { 26524 throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); 26525 } 26526 node[name] = value; 26527 } 26528 }, 26529 26530 // Performs an accept operation with added sanity check to ensure 26531 // required keys are not removed. 26532 acceptRequired: function acceptRequired(node, name) { 26533 this.acceptKey(node, name); 26534 26535 if (!node[name]) { 26536 throw new _exception2['default'](node.type + ' requires ' + name); 26537 } 26538 }, 26539 26540 // Traverses a given array. If mutating, empty respnses will be removed 26541 // for child elements. 26542 acceptArray: function acceptArray(array) { 26543 for (var i = 0, l = array.length; i < l; i++) { 26544 this.acceptKey(array, i); 26545 26546 if (!array[i]) { 26547 array.splice(i, 1); 26548 i--; 26549 l--; 26550 } 26551 } 26552 }, 26553 26554 accept: function accept(object) { 26555 if (!object) { 26556 return; 26557 } 26558 26559 /* istanbul ignore next: Sanity code */ 26560 if (!this[object.type]) { 26561 throw new _exception2['default']('Unknown type: ' + object.type, object); 26562 } 26563 26564 if (this.current) { 26565 this.parents.unshift(this.current); 26566 } 26567 this.current = object; 26568 26569 var ret = this[object.type](object); 26570 26571 this.current = this.parents.shift(); 26572 26573 if (!this.mutating || ret) { 26574 return ret; 26575 } else if (ret !== false) { 26576 return object; 26577 } 26578 }, 26579 26580 Program: function Program(program) { 26581 this.acceptArray(program.body); 26582 }, 26583 26584 MustacheStatement: visitSubExpression, 26585 Decorator: visitSubExpression, 26586 26587 BlockStatement: visitBlock, 26588 DecoratorBlock: visitBlock, 26589 26590 PartialStatement: visitPartial, 26591 PartialBlockStatement: function PartialBlockStatement(partial) { 26592 visitPartial.call(this, partial); 26593 26594 this.acceptKey(partial, 'program'); 26595 }, 26596 26597 ContentStatement: function ContentStatement() /* content */{}, 26598 CommentStatement: function CommentStatement() /* comment */{}, 26599 26600 SubExpression: visitSubExpression, 26601 26602 PathExpression: function PathExpression() /* path */{}, 26603 26604 StringLiteral: function StringLiteral() /* string */{}, 26605 NumberLiteral: function NumberLiteral() /* number */{}, 26606 BooleanLiteral: function BooleanLiteral() /* bool */{}, 26607 UndefinedLiteral: function UndefinedLiteral() /* literal */{}, 26608 NullLiteral: function NullLiteral() /* literal */{}, 26609 26610 Hash: function Hash(hash) { 26611 this.acceptArray(hash.pairs); 26612 }, 26613 HashPair: function HashPair(pair) { 26614 this.acceptRequired(pair, 'value'); 26615 } 26616 }; 26617 26618 function visitSubExpression(mustache) { 26619 this.acceptRequired(mustache, 'path'); 26620 this.acceptArray(mustache.params); 26621 this.acceptKey(mustache, 'hash'); 26622 } 26623 function visitBlock(block) { 26624 visitSubExpression.call(this, block); 26625 26626 this.acceptKey(block, 'program'); 26627 this.acceptKey(block, 'inverse'); 26628 } 26629 function visitPartial(partial) { 26630 this.acceptRequired(partial, 'name'); 26631 this.acceptArray(partial.params); 26632 this.acceptKey(partial, 'hash'); 26633 } 26634 26635 exports['default'] = Visitor; 26636 module.exports = exports['default']; 26637 26638/***/ }), 26639/* 40 */ 26640/***/ (function(module, exports, __webpack_require__) { 26641 26642 'use strict'; 26643 26644 var _interopRequireDefault = __webpack_require__(1)['default']; 26645 26646 exports.__esModule = true; 26647 exports.SourceLocation = SourceLocation; 26648 exports.id = id; 26649 exports.stripFlags = stripFlags; 26650 exports.stripComment = stripComment; 26651 exports.preparePath = preparePath; 26652 exports.prepareMustache = prepareMustache; 26653 exports.prepareRawBlock = prepareRawBlock; 26654 exports.prepareBlock = prepareBlock; 26655 exports.prepareProgram = prepareProgram; 26656 exports.preparePartialBlock = preparePartialBlock; 26657 26658 var _exception = __webpack_require__(6); 26659 26660 var _exception2 = _interopRequireDefault(_exception); 26661 26662 function validateClose(open, close) { 26663 close = close.path ? close.path.original : close; 26664 26665 if (open.path.original !== close) { 26666 var errorNode = { loc: open.path.loc }; 26667 26668 throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode); 26669 } 26670 } 26671 26672 function SourceLocation(source, locInfo) { 26673 this.source = source; 26674 this.start = { 26675 line: locInfo.first_line, 26676 column: locInfo.first_column 26677 }; 26678 this.end = { 26679 line: locInfo.last_line, 26680 column: locInfo.last_column 26681 }; 26682 } 26683 26684 function id(token) { 26685 if (/^\[.*\]$/.test(token)) { 26686 return token.substr(1, token.length - 2
vendor: 4,300 bytes, lines 26686-26870
26686); 26687 } else { 26688 return token; 26689 } 26690 } 26691 26692 function stripFlags(open, close) { 26693 return { 26694 open: open.charAt(2) === '~', 26695 close: close.charAt(close.length - 3) === '~' 26696 }; 26697 } 26698 26699 function stripComment(comment) { 26700 return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, ''); 26701 } 26702 26703 function preparePath(data, parts, loc) { 26704 loc = this.locInfo(loc); 26705 26706 var original = data ? '@' : '', 26707 dig = [], 26708 depth = 0; 26709 26710 for (var i = 0, l = parts.length; i < l; i++) { 26711 var part = parts[i].part, 26712 26713 // If we have [] syntax then we do not treat path references as operators, 26714 // i.e. foo.[this] resolves to approximately context.foo['this'] 26715 isLiteral = parts[i].original !== part; 26716 original += (parts[i].separator || '') + part; 26717 26718 if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { 26719 if (dig.length > 0) { 26720 throw new _exception2['default']('Invalid path: ' + original, { loc: loc }); 26721 } else if (part === '..') { 26722 depth++; 26723 } 26724 } else { 26725 dig.push(part); 26726 } 26727 } 26728 26729 return { 26730 type: 'PathExpression', 26731 data: data, 26732 depth: depth, 26733 parts: dig, 26734 original: original, 26735 loc: loc 26736 }; 26737 } 26738 26739 function prepareMustache(path, params, hash, open, strip, locInfo) { 26740 // Must use charAt to support IE pre-10 26741 var escapeFlag = open.charAt(3) || open.charAt(2), 26742 escaped = escapeFlag !== '{' && escapeFlag !== '&'; 26743 26744 var decorator = /\*/.test(open); 26745 return { 26746 type: decorator ? 'Decorator' : 'MustacheStatement', 26747 path: path, 26748 params: params, 26749 hash: hash, 26750 escaped: escaped, 26751 strip: strip, 26752 loc: this.locInfo(locInfo) 26753 }; 26754 } 26755 26756 function prepareRawBlock(openRawBlock, contents, close, locInfo) { 26757 validateClose(openRawBlock, close); 26758 26759 locInfo = this.locInfo(locInfo); 26760 var program = { 26761 type: 'Program', 26762 body: contents, 26763 strip: {}, 26764 loc: locInfo 26765 }; 26766 26767 return { 26768 type: 'BlockStatement', 26769 path: openRawBlock.path, 26770 params: openRawBlock.params, 26771 hash: openRawBlock.hash, 26772 program: program, 26773 openStrip: {}, 26774 inverseStrip: {}, 26775 closeStrip: {}, 26776 loc: locInfo 26777 }; 26778 } 26779 26780 function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { 26781 if (close && close.path) { 26782 validateClose(openBlock, close); 26783 } 26784 26785 var decorator = /\*/.test(openBlock.open); 26786 26787 program.blockParams = openBlock.blockParams; 26788 26789 var inverse = undefined, 26790 inverseStrip = undefined; 26791 26792 if (inverseAndProgram) { 26793 if (decorator) { 26794 throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram); 26795 } 26796 26797 if (inverseAndProgram.chain) { 26798 inverseAndProgram.program.body[0].closeStrip = close.strip; 26799 } 26800 26801 inverseStrip = inverseAndProgram.strip; 26802 inverse = inverseAndProgram.program; 26803 } 26804 26805 if (inverted) { 26806 inverted = inverse; 26807 inverse = program; 26808 program = inverted; 26809 } 26810 26811 return { 26812 type: decorator ? 'DecoratorBlock' : 'BlockStatement', 26813 path: openBlock.path, 26814 params: openBlock.params, 26815 hash: openBlock.hash, 26816 program: program, 26817 inverse: inverse, 26818 openStrip: openBlock.strip, 26819 inverseStrip: inverseStrip, 26820 closeStrip: close && close.strip, 26821 loc: this.locInfo(locInfo) 26822 }; 26823 } 26824 26825 function prepareProgram(statements, loc) { 26826 if (!loc && statements.length) { 26827 var firstLoc = statements[0].loc, 26828 lastLoc = statements[statements.length - 1].loc; 26829 26830 /* istanbul ignore else */ 26831 if (firstLoc && lastLoc) { 26832 loc = { 26833 source: firstLoc.source, 26834 start: { 26835 line: firstLoc.start.line, 26836 column: firstLoc.start.column 26837 }, 26838 end: { 26839 line: lastLoc.end.line, 26840 column: lastLoc.end.column 26841 } 26842 }; 26843 } 26844 } 26845 26846 return { 26847 type: 'Program', 26848 body: statements, 26849 strip: {}, 26850 loc: loc 26851 }; 26852 } 26853 26854 function preparePartialBlock(open, program, close, locInfo) { 26855 validateClose(open, close); 26856 26857 return { 26858 type: 'PartialBlockStatement', 26859 name: open.path, 26860 params: open.params, 26861 hash: open.hash, 26862 program: program, 26863 openStrip: open.strip, 26864 closeStrip: close && close.strip, 26865 loc: this.locInfo(locInfo) 26866 }; 26867 } 26868 26869/***/ }), 26870/*
vendor: 2,694 bytes, lines 26870-26963
2687041 */ 26871/***/ (function(module, exports, __webpack_require__) { 26872 26873 /* eslint-disable new-cap */ 26874 26875 'use strict'; 26876 26877 var _interopRequireDefault = __webpack_require__(1)['default']; 26878 26879 exports.__esModule = true; 26880 exports.Compiler = Compiler; 26881 exports.precompile = precompile; 26882 exports.compile = compile; 26883 26884 var _exception = __webpack_require__(6); 26885 26886 var _exception2 = _interopRequireDefault(_exception); 26887 26888 var _utils = __webpack_require__(5); 26889 26890 var _ast = __webpack_require__(35); 26891 26892 var _ast2 = _interopRequireDefault(_ast); 26893 26894 var slice = [].slice; 26895 26896 function Compiler() {} 26897 26898 // the foundHelper register will disambiguate helper lookup from finding a 26899 // function in a context. This is necessary for mustache compatibility, which 26900 // requires that context functions in blocks are evaluated by blockHelperMissing, 26901 // and then proceed as if the resulting value was provided to blockHelperMissing. 26902 26903 Compiler.prototype = { 26904 compiler: Compiler, 26905 26906 equals: function equals(other) { 26907 var len = this.opcodes.length; 26908 if (other.opcodes.length !== len) { 26909 return false; 26910 } 26911 26912 for (var i = 0; i < len; i++) { 26913 var opcode = this.opcodes[i], 26914 otherOpcode = other.opcodes[i]; 26915 if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { 26916 return false; 26917 } 26918 } 26919 26920 // We know that length is the same between the two arrays because they are directly tied 26921 // to the opcode behavior above. 26922 len = this.children.length; 26923 for (var i = 0; i < len; i++) { 26924 if (!this.children[i].equals(other.children[i])) { 26925 return false; 26926 } 26927 } 26928 26929 return true; 26930 }, 26931 26932 guid: 0, 26933 26934 compile: function compile(program, options) { 26935 this.sourceNode = []; 26936 this.opcodes = []; 26937 this.children = []; 26938 this.options = options; 26939 this.stringParams = options.stringParams; 26940 this.trackIds = options.trackIds; 26941 26942 options.blockParams = options.blockParams || []; 26943 26944 // These changes will propagate to the other compiler components 26945 var knownHelpers = options.knownHelpers; 26946 options.knownHelpers = { 26947 'helperMissing': true, 26948 'blockHelperMissing': true, 26949 'each': true, 26950 'if': true, 26951 'unless': true, 26952 'with': true, 26953 'log': true, 26954 'lookup': true 26955 }; 26956 if (knownHelpers) { 26957 // the next line should use "Object.keys", but the code has been like this a long time and changing it, might 26958 // cause backwards-compatibility issues... It's an old library... 26959 // eslint-disable-next-line guard-for-in 26960 for (var _name in knownHelpers) { 26961 this.options.knownHelpers[_name] = knownHelpers[_name]; 26962 } 26963 }
vendor: 7,760 bytes, lines 26963-27229
26963 26964 26965 return this.accept(program); 26966 }, 26967 26968 compileProgram: function compileProgram(program) { 26969 var childCompiler = new this.compiler(), 26970 // eslint-disable-line new-cap 26971 result = childCompiler.compile(program, this.options), 26972 guid = this.guid++; 26973 26974 this.usePartial = this.usePartial || result.usePartial; 26975 26976 this.children[guid] = result; 26977 this.useDepths = this.useDepths || result.useDepths; 26978 26979 return guid; 26980 }, 26981 26982 accept: function accept(node) { 26983 /* istanbul ignore next: Sanity code */ 26984 if (!this[node.type]) { 26985 throw new _exception2['default']('Unknown type: ' + node.type, node); 26986 } 26987 26988 this.sourceNode.unshift(node); 26989 var ret = this[node.type](node); 26990 this.sourceNode.shift(); 26991 return ret; 26992 }, 26993 26994 Program: function Program(program) { 26995 this.options.blockParams.unshift(program.blockParams); 26996 26997 var body = program.body, 26998 bodyLength = body.length; 26999 for (var i = 0; i < bodyLength; i++) { 27000 this.accept(body[i]); 27001 } 27002 27003 this.options.blockParams.shift(); 27004 27005 this.isSimple = bodyLength === 1; 27006 this.blockParams = program.blockParams ? program.blockParams.length : 0; 27007 27008 return this; 27009 }, 27010 27011 BlockStatement: function BlockStatement(block) { 27012 transformLiteralToPath(block); 27013 27014 var program = block.program, 27015 inverse = block.inverse; 27016 27017 program = program && this.compileProgram(program); 27018 inverse = inverse && this.compileProgram(inverse); 27019 27020 var type = this.classifySexpr(block); 27021 27022 if (type === 'helper') { 27023 this.helperSexpr(block, program, inverse); 27024 } else if (type === 'simple') { 27025 this.simpleSexpr(block); 27026 27027 // now that the simple mustache is resolved, we need to 27028 // evaluate it by executing `blockHelperMissing` 27029 this.opcode('pushProgram', program); 27030 this.opcode('pushProgram', inverse); 27031 this.opcode('emptyHash'); 27032 this.opcode('blockValue', block.path.original); 27033 } else { 27034 this.ambiguousSexpr(block, program, inverse); 27035 27036 // now that the simple mustache is resolved, we need to 27037 // evaluate it by executing `blockHelperMissing` 27038 this.opcode('pushProgram', program); 27039 this.opcode('pushProgram', inverse); 27040 this.opcode('emptyHash'); 27041 this.opcode('ambiguousBlockValue'); 27042 } 27043 27044 this.opcode('append'); 27045 }, 27046 27047 DecoratorBlock: function DecoratorBlock(decorator) { 27048 var program = decorator.program && this.compileProgram(decorator.program); 27049 var params = this.setupFullMustacheParams(decorator, program, undefined), 27050 path = decorator.path; 27051 27052 this.useDecorators = true; 27053 this.opcode('registerDecorator', params.length, path.original); 27054 }, 27055 27056 PartialStatement: function PartialStatement(partial) { 27057 this.usePartial = true; 27058 27059 var program = partial.program; 27060 if (program) { 27061 program = this.compileProgram(partial.program); 27062 } 27063 27064 var params = partial.params; 27065 if (params.length > 1) { 27066 throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial); 27067 } else if (!params.length) { 27068 if (this.options.explicitPartialContext) { 27069 this.opcode('pushLiteral', 'undefined'); 27070 } else { 27071 params.push({ type: 'PathExpression', parts: [], depth: 0 }); 27072 } 27073 } 27074 27075 var partialName = partial.name.original, 27076 isDynamic = partial.name.type === 'SubExpression'; 27077 if (isDynamic) { 27078 this.accept(partial.name); 27079 } 27080 27081 this.setupFullMustacheParams(partial, program, undefined, true); 27082 27083 var indent = partial.indent || ''; 27084 if (this.options.preventIndent && indent) { 27085 this.opcode('appendContent', indent); 27086 indent = ''; 27087 } 27088 27089 this.opcode('invokePartial', isDynamic, partialName, indent); 27090 this.opcode('append'); 27091 }, 27092 PartialBlockStatement: function PartialBlockStatement(partialBlock) { 27093 this.PartialStatement(partialBlock); 27094 }, 27095 27096 MustacheStatement: function MustacheStatement(mustache) { 27097 this.SubExpression(mustache); 27098 27099 if (mustache.escaped && !this.options.noEscape) { 27100 this.opcode('appendEscaped'); 27101 } else { 27102 this.opcode('append'); 27103 } 27104 }, 27105 Decorator: function Decorator(decorator) { 27106 this.DecoratorBlock(decorator); 27107 }, 27108 27109 ContentStatement: function ContentStatement(content) { 27110 if (content.value) { 27111 this.opcode('appendContent', content.value); 27112 } 27113 }, 27114 27115 CommentStatement: function CommentStatement() {}, 27116 27117 SubExpression: function SubExpression(sexpr) { 27118 transformLiteralToPath(sexpr); 27119 var type = this.classifySexpr(sexpr); 27120 27121 if (type === 'simple') { 27122 this.simpleSexpr(sexpr); 27123 } else if (type === 'helper') { 27124 this.helperSexpr(sexpr); 27125 } else { 27126 this.ambiguousSexpr(sexpr); 27127 } 27128 }, 27129 ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { 27130 var path = sexpr.path, 27131 name = path.parts[0], 27132 isBlock = program != null || inverse != null; 27133 27134 this.opcode('getContext', path.depth); 27135 27136 this.opcode('pushProgram', program); 27137 this.opcode('pushProgram', inverse); 27138 27139 path.strict = true; 27140 this.accept(path); 27141 27142 this.opcode('invokeAmbiguous', name, isBlock); 27143 }, 27144 27145 simpleSexpr: function simpleSexpr(sexpr) { 27146 var path = sexpr.path; 27147 path.strict = true; 27148 this.accept(path); 27149 this.opcode('resolvePossibleLambda'); 27150 }, 27151 27152 helperSexpr: function helperSexpr(sexpr, program, inverse) { 27153 var params = this.setupFullMustacheParams(sexpr, program, inverse), 27154 path = sexpr.path, 27155 name = path.parts[0]; 27156 27157 if (this.options.knownHelpers[name]) { 27158 this.opcode('invokeKnownHelper', params.length, name); 27159 } else if (this.options.knownHelpersOnly) { 27160 throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); 27161 } else { 27162 path.strict = true; 27163 path.falsy = true; 27164 27165 this.accept(path); 27166 this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path)); 27167 } 27168 }, 27169 27170 PathExpression: function PathExpression(path) { 27171 this.addDepth(path.depth); 27172 this.opcode('getContext', path.depth); 27173 27174 var name = path.parts[0], 27175 scoped = _ast2['default'].helpers.scopedId(path), 27176 blockParamId = !path.depth && !scoped && this.blockParamIndex(name); 27177 27178 if (blockParamId) { 27179 this.opcode('lookupBlockParam', blockParamId, path.parts); 27180 } else if (!name) { 27181 // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` 27182 this.opcode('pushContext'); 27183 } else if (path.data) { 27184 this.options.data = true; 27185 this.opcode('lookupData', path.depth, path.parts, path.strict); 27186 } else { 27187 this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); 27188 } 27189 }, 27190 27191 StringLiteral: function StringLiteral(string) { 27192 this.opcode('pushString', string.value); 27193 }, 27194 27195 NumberLiteral: function NumberLiteral(number) { 27196 this.opcode('pushLiteral', number.value); 27197 }, 27198 27199 BooleanLiteral: function BooleanLiteral(bool) { 27200 this.opcode('pushLiteral', bool.value); 27201 }, 27202 27203 UndefinedLiteral: function UndefinedLiteral() { 27204 this.opcode('pushLiteral', 'undefined'); 27205 }, 27206 27207 NullLiteral: function NullLiteral() { 27208 this.opcode('pushLiteral', 'null'); 27209 }, 27210 27211 Hash: function Hash(hash) { 27212 var pairs = hash.pairs, 27213 i = 0, 27214 l = pairs.length; 27215 27216 this.opcode('pushHash'); 27217 27218 for (; i < l; i++) { 27219 this.pushParam(pairs[i].value); 27220 } 27221 while (i--) { 27222 this.opcode('assignToHash', pairs[i].key); 27223 } 27224 this.opcode('popHash'); 27225 }, 27226 27227 // HELPERS 27228 opcode: function opcode(name) { 27229 this.opcodes.push({
vendor: 5,637 bytes, lines 27229-27414
27229 opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc }); 27230 }, 27231 27232 addDepth: function addDepth(depth) { 27233 if (!depth) { 27234 return; 27235 } 27236 27237 this.useDepths = true; 27238 }, 27239 27240 classifySexpr: function classifySexpr(sexpr) { 27241 var isSimple = _ast2['default'].helpers.simpleId(sexpr.path); 27242 27243 var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); 27244 27245 // a mustache is an eligible helper if: 27246 // * its id is simple (a single part, not `this` or `..`) 27247 var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr); 27248 27249 // if a mustache is an eligible helper but not a definite 27250 // helper, it is ambiguous, and will be resolved in a later 27251 // pass or at runtime. 27252 var isEligible = !isBlockParam && (isHelper || isSimple); 27253 27254 // if ambiguous, we can possibly resolve the ambiguity now 27255 // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. 27256 if (isEligible && !isHelper) { 27257 var _name2 = sexpr.path.parts[0], 27258 options = this.options; 27259 27260 if (options.knownHelpers[_name2]) { 27261 isHelper = true; 27262 } else if (options.knownHelpersOnly) { 27263 isEligible = false; 27264 } 27265 } 27266 27267 if (isHelper) { 27268 return 'helper'; 27269 } else if (isEligible) { 27270 return 'ambiguous'; 27271 } else { 27272 return 'simple'; 27273 } 27274 }, 27275 27276 pushParams: function pushParams(params) { 27277 for (var i = 0, l = params.length; i < l; i++) { 27278 this.pushParam(params[i]); 27279 } 27280 }, 27281 27282 pushParam: function pushParam(val) { 27283 var value = val.value != null ? val.value : val.original || ''; 27284 27285 if (this.stringParams) { 27286 if (value.replace) { 27287 value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); 27288 } 27289 27290 if (val.depth) { 27291 this.addDepth(val.depth); 27292 } 27293 this.opcode('getContext', val.depth || 0); 27294 this.opcode('pushStringParam', value, val.type); 27295 27296 if (val.type === 'SubExpression') { 27297 // SubExpressions get evaluated and passed in 27298 // in string params mode. 27299 this.accept(val); 27300 } 27301 } else { 27302 if (this.trackIds) { 27303 var blockParamIndex = undefined; 27304 if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) { 27305 blockParamIndex = this.blockParamIndex(val.parts[0]); 27306 } 27307 if (blockParamIndex) { 27308 var blockParamChild = val.parts.slice(1).join('.'); 27309 this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); 27310 } else { 27311 value = val.original || value; 27312 if (value.replace) { 27313 value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); 27314 } 27315 27316 this.opcode('pushId', val.type, value); 27317 } 27318 } 27319 this.accept(val); 27320 } 27321 }, 27322 27323 setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { 27324 var params = sexpr.params; 27325 this.pushParams(params); 27326 27327 this.opcode('pushProgram', program); 27328 this.opcode('pushProgram', inverse); 27329 27330 if (sexpr.hash) { 27331 this.accept(sexpr.hash); 27332 } else { 27333 this.opcode('emptyHash', omitEmpty); 27334 } 27335 27336 return params; 27337 }, 27338 27339 blockParamIndex: function blockParamIndex(name) { 27340 for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { 27341 var blockParams = this.options.blockParams[depth], 27342 param = blockParams && _utils.indexOf(blockParams, name); 27343 if (blockParams && param >= 0) { 27344 return [depth, param]; 27345 } 27346 } 27347 } 27348 }; 27349 27350 function precompile(input, options, env) { 27351 if (input == null || typeof input !== 'string' && input.type !== 'Program') { 27352 throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); 27353 } 27354 27355 options = options || {}; 27356 if (!('data' in options)) { 27357 options.data = true; 27358 } 27359 if (options.compat) { 27360 options.useDepths = true; 27361 } 27362 27363 var ast = env.parse(input, options), 27364 environment = new env.Compiler().compile(ast, options); 27365 return new env.JavaScriptCompiler().compile(environment, options); 27366 } 27367 27368 function compile(input, options, env) { 27369 if (options === undefined) options = {}; 27370 27371 if (input == null || typeof input !== 'string' && input.type !== 'Program') { 27372 throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); 27373 } 27374 27375 options = _utils.extend({}, options); 27376 if (!('data' in options)) { 27377 options.data = true; 27378 } 27379 if (options.compat) { 27380 options.useDepths = true; 27381 } 27382 27383 var compiled = undefined; 27384 27385 function compileInput() { 27386 var ast = env.parse(input, options), 27387 environment = new env.Compiler().compile(ast, options), 27388 templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); 27389 return env.template(templateSpec); 27390 } 27391 27392 // Template is only compiled on first use and cached after that point. 27393 function ret(context, execOptions) { 27394 if (!compiled) { 27395 compiled = compileInput(); 27396 } 27397 return compiled.call(this, context, execOptions); 27398 } 27399 ret._setup = function (setupOptions) { 27400 if (!compiled) { 27401 compiled = compileInput(); 27402 } 27403 return compiled._setup(setupOptions); 27404 }; 27405 ret._child = function (i, data, blockParams, depths) { 27406 if (!compiled) { 27407 compiled = compileInput(); 27408 } 27409 return compiled._child(i, data, blockParams, depths); 27410 }; 27411 return ret; 27412 } 27413 27414 function argEquals(a, b) {
vendor: 8,012 bytes, lines 27415-27681
27415 if (a === b) { 27416 return true; 27417 } 27418 27419 if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { 27420 for (var i = 0; i < a.length; i++) { 27421 if (!argEquals(a[i], b[i])) { 27422 return false; 27423 } 27424 } 27425 return true; 27426 } 27427 } 27428 27429 function transformLiteralToPath(sexpr) { 27430 if (!sexpr.path.parts) { 27431 var literal = sexpr.path; 27432 // Casting to string here to make false and 0 literal values play nicely with the rest 27433 // of the system. 27434 sexpr.path = { 27435 type: 'PathExpression', 27436 data: false, 27437 depth: 0, 27438 parts: [literal.original + ''], 27439 original: literal.original + '', 27440 loc: literal.loc 27441 }; 27442 } 27443 } 27444 27445/***/ }), 27446/* 42 */ 27447/***/ (function(module, exports, __webpack_require__) { 27448 27449 'use strict'; 27450 27451 var _interopRequireDefault = __webpack_require__(1)['default']; 27452 27453 exports.__esModule = true; 27454 27455 var _base = __webpack_require__(4); 27456 27457 var _exception = __webpack_require__(6); 27458 27459 var _exception2 = _interopRequireDefault(_exception); 27460 27461 var _utils = __webpack_require__(5); 27462 27463 var _codeGen = __webpack_require__(43); 27464 27465 var _codeGen2 = _interopRequireDefault(_codeGen); 27466 27467 function Literal(value) { 27468 this.value = value; 27469 } 27470 27471 function JavaScriptCompiler() {} 27472 27473 JavaScriptCompiler.prototype = { 27474 // PUBLIC API: You can override these methods in a subclass to provide 27475 // alternative compiled forms for name lookup and buffering semantics 27476 nameLookup: function nameLookup(parent, name /* , type*/) { 27477 if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { 27478 return [parent, '.', name]; 27479 } else { 27480 return [parent, '[', JSON.stringify(name), ']']; 27481 } 27482 }, 27483 depthedLookup: function depthedLookup(name) { 27484 return [this.aliasable('container.lookup'), '(depths, "', name, '")']; 27485 }, 27486 27487 compilerInfo: function compilerInfo() { 27488 var revision = _base.COMPILER_REVISION, 27489 versions = _base.REVISION_CHANGES[revision]; 27490 return [revision, versions]; 27491 }, 27492 27493 appendToBuffer: function appendToBuffer(source, location, explicit) { 27494 // Force a source as this simplifies the merge logic. 27495 if (!_utils.isArray(source)) { 27496 source = [source]; 27497 } 27498 source = this.source.wrap(source, location); 27499 27500 if (this.environment.isSimple) { 27501 return ['return ', source, ';']; 27502 } else if (explicit) { 27503 // This is a case where the buffer operation occurs as a child of another 27504 // construct, generally braces. We have to explicitly output these buffer 27505 // operations to ensure that the emitted code goes in the correct location. 27506 return ['buffer += ', source, ';']; 27507 } else { 27508 source.appendToBuffer = true; 27509 return source; 27510 } 27511 }, 27512 27513 initializeBuffer: function initializeBuffer() { 27514 return this.quotedString(''); 27515 }, 27516 // END PUBLIC API 27517 27518 compile: function compile(environment, options, context, asObject) { 27519 this.environment = environment; 27520 this.options = options; 27521 this.stringParams = this.options.stringParams; 27522 this.trackIds = this.options.trackIds; 27523 this.precompile = !asObject; 27524 27525 this.name = this.environment.name; 27526 this.isChild = !!context; 27527 this.context = context || { 27528 decorators: [], 27529 programs: [], 27530 environments: [] 27531 }; 27532 27533 this.preamble(); 27534 27535 this.stackSlot = 0; 27536 this.stackVars = []; 27537 this.aliases = {}; 27538 this.registers = { list: [] }; 27539 this.hashes = []; 27540 this.compileStack = []; 27541 this.inlineStack = []; 27542 this.blockParams = []; 27543 27544 this.compileChildren(environment, options); 27545 27546 this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; 27547 this.useBlockParams = this.useBlockParams || environment.useBlockParams; 27548 27549 var opcodes = environment.opcodes, 27550 opcode = undefined, 27551 firstLoc = undefined, 27552 i = undefined, 27553 l = undefined; 27554 27555 for (i = 0, l = opcodes.length; i < l; i++) { 27556 opcode = opcodes[i]; 27557 27558 this.source.currentLocation = opcode.loc; 27559 firstLoc = firstLoc || opcode.loc; 27560 this[opcode.opcode].apply(this, opcode.args); 27561 } 27562 27563 // Flush any trailing content that might be pending. 27564 this.source.currentLocation = firstLoc; 27565 this.pushSource(''); 27566 27567 /* istanbul ignore next */ 27568 if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { 27569 throw new _exception2['default']('Compile completed with content left on stack'); 27570 } 27571 27572 if (!this.decorators.isEmpty()) { 27573 this.useDecorators = true; 27574 27575 this.decorators.prepend('var decorators = container.decorators;\n'); 27576 this.decorators.push('return fn;'); 27577 27578 if (asObject) { 27579 this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); 27580 } else { 27581 this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); 27582 this.decorators.push('}\n'); 27583 this.decorators = this.decorators.merge(); 27584 } 27585 } else { 27586 this.decorators = undefined; 27587 } 27588 27589 var fn = this.createFunctionContext(asObject); 27590 if (!this.isChild) { 27591 var ret = { 27592 compiler: this.compilerInfo(), 27593 main: fn 27594 }; 27595 27596 if (this.decorators) { 27597 ret.main_d = this.decorators; // eslint-disable-line camelcase 27598 ret.useDecorators = true; 27599 } 27600 27601 var _context = this.context; 27602 var programs = _context.programs; 27603 var decorators = _context.decorators; 27604 27605 for (i = 0, l = programs.length; i < l; i++) { 27606 if (programs[i]) { 27607 ret[i] = programs[i]; 27608 if (decorators[i]) { 27609 ret[i + '_d'] = decorators[i]; 27610 ret.useDecorators = true; 27611 } 27612 } 27613 } 27614 27615 if (this.environment.usePartial) { 27616 ret.usePartial = true; 27617 } 27618 if (this.options.data) { 27619 ret.useData = true; 27620 } 27621 if (this.useDepths) { 27622 ret.useDepths = true; 27623 } 27624 if (this.useBlockParams) { 27625 ret.useBlockParams = true; 27626 } 27627 if (this.options.compat) { 27628 ret.compat = true; 27629 } 27630 27631 if (!asObject) { 27632 ret.compiler = JSON.stringify(ret.compiler); 27633 27634 this.source.currentLocation = { start: { line: 1, column: 0 } }; 27635 ret = this.objectLiteral(ret); 27636 27637 if (options.srcName) { 27638 ret = ret.toStringWithSourceMap({ file: options.destName }); 27639 ret.map = ret.map && ret.map.toString(); 27640 } else { 27641 ret = ret.toString(); 27642 } 27643 } else { 27644 ret.compilerOptions = this.options; 27645 } 27646 27647 return ret; 27648 } else { 27649 return fn; 27650 } 27651 }, 27652 27653 preamble: function preamble() { 27654 // track the last context pushed into place to allow skipping the 27655 // getContext opcode when it would be a noop 27656 this.lastContext = 0; 27657 this.source = new _codeGen2['default'](this.options.srcName); 27658 this.decorators = new _codeGen2['default'](this.options.srcName); 27659 }, 27660 27661 createFunctionContext: function createFunctionContext(asObject) { 27662 var varDeclarations = ''; 27663 27664 var locals = this.stackVars.concat(this.registers.list); 27665 if (locals.length > 0) { 27666 varDeclarations += ', ' + locals.join(', '); 27667 } 27668 27669 // Generate minimizer alias mappings 27670 // 27671 // When using true SourceNodes, this will update all references to the given alias 27672 // as the source nodes are reused in situ. For the non-source node compilation mode, 27673 // aliases will not be used, but this case is already being run on the client and 27674 // we aren't concern about minimizing the template size. 27675 var aliasCount = 0; 27676 for (var alias in this.aliases) { 27677 // eslint-disable-line guard-for-in 27678 var node = this.aliases[alias]; 27679 27680 if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { 27681 varDeclarations += ', alias' + ++aliasCount + '=' + alias;
vendor: 4,556 bytes, lines 27682-27831
27682 node.children[0] = 'alias' + aliasCount; 27683 } 27684 } 27685 27686 var params = ['container', 'depth0', 'helpers', 'partials', 'data']; 27687 27688 if (this.useBlockParams || this.useDepths) { 27689 params.push('blockParams'); 27690 } 27691 if (this.useDepths) { 27692 params.push('depths'); 27693 } 27694 27695 // Perform a second pass over the output to merge content when possible 27696 var source = this.mergeSource(varDeclarations); 27697 27698 if (asObject) { 27699 params.push(source); 27700 27701 return Function.apply(this, params); 27702 } else { 27703 return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); 27704 } 27705 }, 27706 mergeSource: function mergeSource(varDeclarations) { 27707 var isSimple = this.environment.isSimple, 27708 appendOnly = !this.forceBuffer, 27709 appendFirst = undefined, 27710 sourceSeen = undefined, 27711 bufferStart = undefined, 27712 bufferEnd = undefined; 27713 this.source.each(function (line) { 27714 if (line.appendToBuffer) { 27715 if (bufferStart) { 27716 line.prepend(' + '); 27717 } else { 27718 bufferStart = line; 27719 } 27720 bufferEnd = line; 27721 } else { 27722 if (bufferStart) { 27723 if (!sourceSeen) { 27724 appendFirst = true; 27725 } else { 27726 bufferStart.prepend('buffer += '); 27727 } 27728 bufferEnd.add(';'); 27729 bufferStart = bufferEnd = undefined; 27730 } 27731 27732 sourceSeen = true; 27733 if (!isSimple) { 27734 appendOnly = false; 27735 } 27736 } 27737 }); 27738 27739 if (appendOnly) { 27740 if (bufferStart) { 27741 bufferStart.prepend('return '); 27742 bufferEnd.add(';'); 27743 } else if (!sourceSeen) { 27744 this.source.push('return "";'); 27745 } 27746 } else { 27747 varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); 27748 27749 if (bufferStart) { 27750 bufferStart.prepend('return buffer + '); 27751 bufferEnd.add(';'); 27752 } else { 27753 this.source.push('return buffer;'); 27754 } 27755 } 27756 27757 if (varDeclarations) { 27758 this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); 27759 } 27760 27761 return this.source.merge(); 27762 }, 27763 27764 // [blockValue] 27765 // 27766 // On stack, before: hash, inverse, program, value 27767 // On stack, after: return value of blockHelperMissing 27768 // 27769 // The purpose of this opcode is to take a block of the form 27770 // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and 27771 // replace it on the stack with the result of properly 27772 // invoking blockHelperMissing. 27773 blockValue: function blockValue(name) { 27774 var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), 27775 params = [this.contextName(0)]; 27776 this.setupHelperArgs(name, 0, params); 27777 27778 var blockName = this.popStack(); 27779 params.splice(1, 0, blockName); 27780 27781 this.push(this.source.functionCall(blockHelperMissing, 'call', params)); 27782 }, 27783 27784 // [ambiguousBlockValue] 27785 // 27786 // On stack, before: hash, inverse, program, value 27787 // Compiler value, before: lastHelper=value of last found helper, if any 27788 // On stack, after, if no lastHelper: same as [blockValue] 27789 // On stack, after, if lastHelper: value 27790 ambiguousBlockValue: function ambiguousBlockValue() { 27791 // We're being a bit cheeky and reusing the options value from the prior exec 27792 var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'), 27793 params = [this.contextName(0)]; 27794 this.setupHelperArgs('', 0, params, true); 27795 27796 this.flushInline(); 27797 27798 var current = this.topStack(); 27799 params.splice(1, 0, current); 27800 27801 this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); 27802 }, 27803 27804 // [appendContent] 27805 // 27806 // On stack, before: ... 27807 // On stack, after: ... 27808 // 27809 // Appends the string value of `content` to the current buffer 27810 appendContent: function appendContent(content) { 27811 if (this.pendingContent) { 27812 content = this.pendingContent + content; 27813 } else { 27814 this.pendingLocation = this.source.currentLocation; 27815 } 27816 27817 this.pendingContent = content; 27818 }, 27819 27820 // [append] 27821 // 27822 // On stack, before: value, ... 27823 // On stack, after: ... 27824 // 27825 // Coerces `value` to a String and appends it to the current buffer. 27826 // 27827 // If `value` is truthy, or 0, it is coerced into a string and appended 27828 // Otherwise, the empty string is appended 27829 append: function append() { 27830 if (this.isInline()) { 27831 this.replaceStack(function (current) {
vendor: 5,813 bytes, lines 27832-28024
27832 return [' != null ? ', current, ' : ""']; 27833 }); 27834 27835 this.pushSource(this.appendToBuffer(this.popStack())); 27836 } else { 27837 var local = this.popStack(); 27838 this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); 27839 if (this.environment.isSimple) { 27840 this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); 27841 } 27842 } 27843 }, 27844 27845 // [appendEscaped] 27846 // 27847 // On stack, before: value, ... 27848 // On stack, after: ... 27849 // 27850 // Escape `value` and append it to the buffer 27851 appendEscaped: function appendEscaped() { 27852 this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); 27853 }, 27854 27855 // [getContext] 27856 // 27857 // On stack, before: ... 27858 // On stack, after: ... 27859 // Compiler value, after: lastContext=depth 27860 // 27861 // Set the value of the `lastContext` compiler value to the depth 27862 getContext: function getContext(depth) { 27863 this.lastContext = depth; 27864 }, 27865 27866 // [pushContext] 27867 // 27868 // On stack, before: ... 27869 // On stack, after: currentContext, ... 27870 // 27871 // Pushes the value of the current context onto the stack. 27872 pushContext: function pushContext() { 27873 this.pushStackLiteral(this.contextName(this.lastContext)); 27874 }, 27875 27876 // [lookupOnContext] 27877 // 27878 // On stack, before: ... 27879 // On stack, after: currentContext[name], ... 27880 // 27881 // Looks up the value of `name` on the current context and pushes 27882 // it onto the stack. 27883 lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { 27884 var i = 0; 27885 27886 if (!scoped && this.options.compat && !this.lastContext) { 27887 // The depthed query is expected to handle the undefined logic for the root level that 27888 // is implemented below, so we evaluate that directly in compat mode 27889 this.push(this.depthedLookup(parts[i++])); 27890 } else { 27891 this.pushContext(); 27892 } 27893 27894 this.resolvePath('context', parts, i, falsy, strict); 27895 }, 27896 27897 // [lookupBlockParam] 27898 // 27899 // On stack, before: ... 27900 // On stack, after: blockParam[name], ... 27901 // 27902 // Looks up the value of `parts` on the given block param and pushes 27903 // it onto the stack. 27904 lookupBlockParam: function lookupBlockParam(blockParamId, parts) { 27905 this.useBlockParams = true; 27906 27907 this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); 27908 this.resolvePath('context', parts, 1); 27909 }, 27910 27911 // [lookupData] 27912 // 27913 // On stack, before: ... 27914 // On stack, after: data, ... 27915 // 27916 // Push the data lookup operator 27917 lookupData: function lookupData(depth, parts, strict) { 27918 if (!depth) { 27919 this.pushStackLiteral('data'); 27920 } else { 27921 this.pushStackLiteral('container.data(data, ' + depth + ')'); 27922 } 27923 27924 this.resolvePath('data', parts, 0, true, strict); 27925 }, 27926 27927 resolvePath: function resolvePath(type, parts, i, falsy, strict) { 27928 // istanbul ignore next 27929 27930 var _this = this; 27931 27932 if (this.options.strict || this.options.assumeObjects) { 27933 this.push(strictLookup(this.options.strict && strict, this, parts, type)); 27934 return; 27935 } 27936 27937 var len = parts.length; 27938 for (; i < len; i++) { 27939 /* eslint-disable no-loop-func */ 27940 this.replaceStack(function (current) { 27941 var lookup = _this.nameLookup(current, parts[i], type); 27942 // We want to ensure that zero and false are handled properly if the context (falsy flag) 27943 // needs to have the special handling for these values. 27944 if (!falsy) { 27945 return [' != null ? ', lookup, ' : ', current]; 27946 } else { 27947 // Otherwise we can use generic falsy handling 27948 return [' && ', lookup]; 27949 } 27950 }); 27951 /* eslint-enable no-loop-func */ 27952 } 27953 }, 27954 27955 // [resolvePossibleLambda] 27956 // 27957 // On stack, before: value, ... 27958 // On stack, after: resolved value, ... 27959 // 27960 // If the `value` is a lambda, replace it on the stack by 27961 // the return value of the lambda 27962 resolvePossibleLambda: function resolvePossibleLambda() { 27963 this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); 27964 }, 27965 27966 // [pushStringParam] 27967 // 27968 // On stack, before: ... 27969 // On stack, after: string, currentContext, ... 27970 // 27971 // This opcode is designed for use in string mode, which 27972 // provides the string value of a parameter along with its 27973 // depth rather than resolving it immediately. 27974 pushStringParam: function pushStringParam(string, type) { 27975 this.pushContext(); 27976 this.pushString(type); 27977 27978 // If it's a subexpression, the string result 27979 // will be pushed after this opcode. 27980 if (type !== 'SubExpression') { 27981 if (typeof string === 'string') { 27982 this.pushString(string); 27983 } else { 27984 this.pushStackLiteral(string); 27985 } 27986 } 27987 }, 27988 27989 emptyHash: function emptyHash(omitEmpty) { 27990 if (this.trackIds) { 27991 this.push('{}'); // hashIds 27992 } 27993 if (this.stringParams) { 27994 this.push('{}'); // hashContexts 27995 this.push('{}'); // hashTypes 27996 } 27997 this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); 27998 }, 27999 pushHash: function pushHash() { 28000 if (this.hash) { 28001 this.hashes.push(this.hash); 28002 } 28003 this.hash = { values: [], types: [], contexts: [], ids: [] }; 28004 }, 28005 popHash: function popHash() { 28006 var hash = this.hash; 28007 this.hash = this.hashes.pop(); 28008 28009 if (this.trackIds) { 28010 this.push(this.objectLiteral(hash.ids)); 28011 } 28012 if (this.stringParams) { 28013 this.push(this.objectLiteral(hash.contexts)); 28014 this.push(this.objectLiteral(hash.types)); 28015 } 28016 28017 this.push(this.objectLiteral(hash.values)); 28018 }, 28019 28020 // [pushString] 28021 // 28022 // On stack, before: ... 28023 // On stack, after: quotedString(string), ... 28024 //
vendor: 6,915 bytes, lines 28025-28238
28025 // Push a quoted version of `string` onto the stack 28026 pushString: function pushString(string) { 28027 this.pushStackLiteral(this.quotedString(string)); 28028 }, 28029 28030 // [pushLiteral] 28031 // 28032 // On stack, before: ... 28033 // On stack, after: value, ... 28034 // 28035 // Pushes a value onto the stack. This operation prevents 28036 // the compiler from creating a temporary variable to hold 28037 // it. 28038 pushLiteral: function pushLiteral(value) { 28039 this.pushStackLiteral(value); 28040 }, 28041 28042 // [pushProgram] 28043 // 28044 // On stack, before: ... 28045 // On stack, after: program(guid), ... 28046 // 28047 // Push a program expression onto the stack. This takes 28048 // a compile-time guid and converts it into a runtime-accessible 28049 // expression. 28050 pushProgram: function pushProgram(guid) { 28051 if (guid != null) { 28052 this.pushStackLiteral(this.programExpression(guid)); 28053 } else { 28054 this.pushStackLiteral(null); 28055 } 28056 }, 28057 28058 // [registerDecorator] 28059 // 28060 // On stack, before: hash, program, params..., ... 28061 // On stack, after: ... 28062 // 28063 // Pops off the decorator's parameters, invokes the decorator, 28064 // and inserts the decorator into the decorators list. 28065 registerDecorator: function registerDecorator(paramSize, name) { 28066 var foundDecorator = this.nameLookup('decorators', name, 'decorator'), 28067 options = this.setupHelperArgs(name, paramSize); 28068 28069 this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); 28070 }, 28071 28072 // [invokeHelper] 28073 // 28074 // On stack, before: hash, inverse, program, params..., ... 28075 // On stack, after: result of helper invocation 28076 // 28077 // Pops off the helper's parameters, invokes the helper, 28078 // and pushes the helper's return value onto the stack. 28079 // 28080 // If the helper is not found, `helperMissing` is called. 28081 invokeHelper: function invokeHelper(paramSize, name, isSimple) { 28082 var nonHelper = this.popStack(), 28083 helper = this.setupHelper(paramSize, name), 28084 simple = isSimple ? [helper.name, ' || '] : ''; 28085 28086 var lookup = ['('].concat(simple, nonHelper); 28087 if (!this.options.strict) { 28088 lookup.push(' || ', this.aliasable('helpers.helperMissing')); 28089 } 28090 lookup.push(')'); 28091 28092 this.push(this.source.functionCall(lookup, 'call', helper.callParams)); 28093 }, 28094 28095 // [invokeKnownHelper] 28096 // 28097 // On stack, before: hash, inverse, program, params..., ... 28098 // On stack, after: result of helper invocation 28099 // 28100 // This operation is used when the helper is known to exist, 28101 // so a `helperMissing` fallback is not required. 28102 invokeKnownHelper: function invokeKnownHelper(paramSize, name) { 28103 var helper = this.setupHelper(paramSize, name); 28104 this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); 28105 }, 28106 28107 // [invokeAmbiguous] 28108 // 28109 // On stack, before: hash, inverse, program, params..., ... 28110 // On stack, after: result of disambiguation 28111 // 28112 // This operation is used when an expression like `{{foo}}` 28113 // is provided, but we don't know at compile-time whether it 28114 // is a helper or a path. 28115 // 28116 // This operation emits more code than the other options, 28117 // and can be avoided by passing the `knownHelpers` and 28118 // `knownHelpersOnly` flags at compile-time. 28119 invokeAmbiguous: function invokeAmbiguous(name, helperCall) { 28120 this.useRegister('helper'); 28121 28122 var nonHelper = this.popStack(); 28123 28124 this.emptyHash(); 28125 var helper = this.setupHelper(0, name, helperCall); 28126 28127 var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); 28128 28129 var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; 28130 if (!this.options.strict) { 28131 lookup[0] = '(helper = '; 28132 lookup.push(' != null ? helper : ', this.aliasable('helpers.helperMissing')); 28133 } 28134 28135 this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); 28136 }, 28137 28138 // [invokePartial] 28139 // 28140 // On stack, before: context, ... 28141 // On stack after: result of partial invocation 28142 // 28143 // This operation pops off a context, invokes a partial with that context, 28144 // and pushes the result of the invocation back. 28145 invokePartial: function invokePartial(isDynamic, name, indent) { 28146 var params = [], 28147 options = this.setupParams(name, 1, params); 28148 28149 if (isDynamic) { 28150 name = this.popStack(); 28151 delete options.name; 28152 } 28153 28154 if (indent) { 28155 options.indent = JSON.stringify(indent); 28156 } 28157 options.helpers = 'helpers'; 28158 options.partials = 'partials'; 28159 options.decorators = 'container.decorators'; 28160 28161 if (!isDynamic) { 28162 params.unshift(this.nameLookup('partials', name, 'partial')); 28163 } else { 28164 params.unshift(name); 28165 } 28166 28167 if (this.options.compat) { 28168 options.depths = 'depths'; 28169 } 28170 options = this.objectLiteral(options); 28171 params.push(options); 28172 28173 this.push(this.source.functionCall('container.invokePartial', '', params)); 28174 }, 28175 28176 // [assignToHash] 28177 // 28178 // On stack, before: value, ..., hash, ... 28179 // On stack, after: ..., hash, ... 28180 // 28181 // Pops a value off the stack and assigns it to the current hash 28182 assignToHash: function assignToHash(key) { 28183 var value = this.popStack(), 28184 context = undefined, 28185 type = undefined, 28186 id = undefined; 28187 28188 if (this.trackIds) { 28189 id = this.popStack(); 28190 } 28191 if (this.stringParams) { 28192 type = this.popStack(); 28193 context = this.popStack(); 28194 } 28195 28196 var hash = this.hash; 28197 if (context) { 28198 hash.contexts[key] = context; 28199 } 28200 if (type) { 28201 hash.types[key] = type; 28202 } 28203 if (id) { 28204 hash.ids[key] = id; 28205 } 28206 hash.values[key] = value; 28207 }, 28208 28209 pushId: function pushId(type, name, child) { 28210 if (type === 'BlockParam') { 28211 this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); 28212 } else if (type === 'PathExpression') { 28213 this.pushString(name); 28214 } else if (type === 'SubExpression') { 28215 this.pushStackLiteral('true'); 28216 } else { 28217 this.pushStackLiteral('null'); 28218 } 28219 }, 28220 28221 // HELPERS 28222 28223 compiler: JavaScriptCompiler, 28224 28225 compileChildren: function compileChildren(environment, options) { 28226 var children = environment.children, 28227 child = undefined, 28228 compiler = undefined; 28229 28230 for (var i = 0, l = children.length; i < l; i++) { 28231 child = children[i]; 28232 compiler = new this.compiler(); // eslint-disable-line new-cap 28233 28234 var existing = this.matchExistingProgram(child); 28235 28236 if (existing == null) { 28237 this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children 28238 var index = this.context.programs.length
vendor: 8,183 bytes, lines 28238-28526
28238; 28239 child.index = index; 28240 child.name = 'program' + index; 28241 this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); 28242 this.context.decorators[index] = compiler.decorators; 28243 this.context.environments[index] = child; 28244 28245 this.useDepths = this.useDepths || compiler.useDepths; 28246 this.useBlockParams = this.useBlockParams || compiler.useBlockParams; 28247 child.useDepths = this.useDepths; 28248 child.useBlockParams = this.useBlockParams; 28249 } else { 28250 child.index = existing.index; 28251 child.name = 'program' + existing.index; 28252 28253 this.useDepths = this.useDepths || existing.useDepths; 28254 this.useBlockParams = this.useBlockParams || existing.useBlockParams; 28255 } 28256 } 28257 }, 28258 matchExistingProgram: function matchExistingProgram(child) { 28259 for (var i = 0, len = this.context.environments.length; i < len; i++) { 28260 var environment = this.context.environments[i]; 28261 if (environment && environment.equals(child)) { 28262 return environment; 28263 } 28264 } 28265 }, 28266 28267 programExpression: function programExpression(guid) { 28268 var child = this.environment.children[guid], 28269 programParams = [child.index, 'data', child.blockParams]; 28270 28271 if (this.useBlockParams || this.useDepths) { 28272 programParams.push('blockParams'); 28273 } 28274 if (this.useDepths) { 28275 programParams.push('depths'); 28276 } 28277 28278 return 'container.program(' + programParams.join(', ') + ')'; 28279 }, 28280 28281 useRegister: function useRegister(name) { 28282 if (!this.registers[name]) { 28283 this.registers[name] = true; 28284 this.registers.list.push(name); 28285 } 28286 }, 28287 28288 push: function push(expr) { 28289 if (!(expr instanceof Literal)) { 28290 expr = this.source.wrap(expr); 28291 } 28292 28293 this.inlineStack.push(expr); 28294 return expr; 28295 }, 28296 28297 pushStackLiteral: function pushStackLiteral(item) { 28298 this.push(new Literal(item)); 28299 }, 28300 28301 pushSource: function pushSource(source) { 28302 if (this.pendingContent) { 28303 this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); 28304 this.pendingContent = undefined; 28305 } 28306 28307 if (source) { 28308 this.source.push(source); 28309 } 28310 }, 28311 28312 replaceStack: function replaceStack(callback) { 28313 var prefix = ['('], 28314 stack = undefined, 28315 createdStack = undefined, 28316 usedLiteral = undefined; 28317 28318 /* istanbul ignore next */ 28319 if (!this.isInline()) { 28320 throw new _exception2['default']('replaceStack on non-inline'); 28321 } 28322 28323 // We want to merge the inline statement into the replacement statement via ',' 28324 var top = this.popStack(true); 28325 28326 if (top instanceof Literal) { 28327 // Literals do not need to be inlined 28328 stack = [top.value]; 28329 prefix = ['(', stack]; 28330 usedLiteral = true; 28331 } else { 28332 // Get or create the current stack name for use by the inline 28333 createdStack = true; 28334 var _name = this.incrStack(); 28335 28336 prefix = ['((', this.push(_name), ' = ', top, ')']; 28337 stack = this.topStack(); 28338 } 28339 28340 var item = callback.call(this, stack); 28341 28342 if (!usedLiteral) { 28343 this.popStack(); 28344 } 28345 if (createdStack) { 28346 this.stackSlot--; 28347 } 28348 this.push(prefix.concat(item, ')')); 28349 }, 28350 28351 incrStack: function incrStack() { 28352 this.stackSlot++; 28353 if (this.stackSlot > this.stackVars.length) { 28354 this.stackVars.push('stack' + this.stackSlot); 28355 } 28356 return this.topStackName(); 28357 }, 28358 topStackName: function topStackName() { 28359 return 'stack' + this.stackSlot; 28360 }, 28361 flushInline: function flushInline() { 28362 var inlineStack = this.inlineStack; 28363 this.inlineStack = []; 28364 for (var i = 0, len = inlineStack.length; i < len; i++) { 28365 var entry = inlineStack[i]; 28366 /* istanbul ignore if */ 28367 if (entry instanceof Literal) { 28368 this.compileStack.push(entry); 28369 } else { 28370 var stack = this.incrStack(); 28371 this.pushSource([stack, ' = ', entry, ';']); 28372 this.compileStack.push(stack); 28373 } 28374 } 28375 }, 28376 isInline: function isInline() { 28377 return this.inlineStack.length; 28378 }, 28379 28380 popStack: function popStack(wrapped) { 28381 var inline = this.isInline(), 28382 item = (inline ? this.inlineStack : this.compileStack).pop(); 28383 28384 if (!wrapped && item instanceof Literal) { 28385 return item.value; 28386 } else { 28387 if (!inline) { 28388 /* istanbul ignore next */ 28389 if (!this.stackSlot) { 28390 throw new _exception2['default']('Invalid stack pop'); 28391 } 28392 this.stackSlot--; 28393 } 28394 return item; 28395 } 28396 }, 28397 28398 topStack: function topStack() { 28399 var stack = this.isInline() ? this.inlineStack : this.compileStack, 28400 item = stack[stack.length - 1]; 28401 28402 /* istanbul ignore if */ 28403 if (item instanceof Literal) { 28404 return item.value; 28405 } else { 28406 return item; 28407 } 28408 }, 28409 28410 contextName: function contextName(context) { 28411 if (this.useDepths && context) { 28412 return 'depths[' + context + ']'; 28413 } else { 28414 return 'depth' + context; 28415 } 28416 }, 28417 28418 quotedString: function quotedString(str) { 28419 return this.source.quotedString(str); 28420 }, 28421 28422 objectLiteral: function objectLiteral(obj) { 28423 return this.source.objectLiteral(obj); 28424 }, 28425 28426 aliasable: function aliasable(name) { 28427 var ret = this.aliases[name]; 28428 if (ret) { 28429 ret.referenceCount++; 28430 return ret; 28431 } 28432 28433 ret = this.aliases[name] = this.source.wrap(name); 28434 ret.aliasable = true; 28435 ret.referenceCount = 1; 28436 28437 return ret; 28438 }, 28439 28440 setupHelper: function setupHelper(paramSize, name, blockHelper) { 28441 var params = [], 28442 paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); 28443 var foundHelper = this.nameLookup('helpers', name, 'helper'), 28444 callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})'); 28445 28446 return { 28447 params: params, 28448 paramsInit: paramsInit, 28449 name: foundHelper, 28450 callParams: [callContext].concat(params) 28451 }; 28452 }, 28453 28454 setupParams: function setupParams(helper, paramSize, params) { 28455 var options = {}, 28456 contexts = [], 28457 types = [], 28458 ids = [], 28459 objectArgs = !params, 28460 param = undefined; 28461 28462 if (objectArgs) { 28463 params = []; 28464 } 28465 28466 options.name = this.quotedString(helper); 28467 options.hash = this.popStack(); 28468 28469 if (this.trackIds) { 28470 options.hashIds = this.popStack(); 28471 } 28472 if (this.stringParams) { 28473 options.hashTypes = this.popStack(); 28474 options.hashContexts = this.popStack(); 28475 } 28476 28477 var inverse = this.popStack(), 28478 program = this.popStack(); 28479 28480 // Avoid setting fn and inverse if neither are set. This allows 28481 // helpers to do a check for `if (options.fn)` 28482 if (program || inverse) { 28483 options.fn = program || 'container.noop'; 28484 options.inverse = inverse || 'container.noop'; 28485 } 28486 28487 // The parameters go on to the stack in order (making sure that they are evaluated in order) 28488 // so we need to pop them off the stack in reverse order 28489 var i = paramSize; 28490 while (i--) { 28491 param = this.popStack(); 28492 params[i] = param; 28493 28494 if (this.trackIds) { 28495 ids[i] = this.popStack(); 28496 } 28497 if (this.stringParams) { 28498 types[i] = this.popStack(); 28499 contexts[i] = this.popStack(); 28500 } 28501 } 28502 28503 if (objectArgs) { 28504 options.args = this.source.generateArray(params); 28505 } 28506 28507 if (this.trackIds) { 28508 options.ids = this.source.generateArray(ids); 28509 } 28510 if (this.stringParams) { 28511 options.types = this.source.generateArray(types); 28512 options.contexts = this.source.generateArray(contexts); 28513 } 28514 28515 if (this.options.data) { 28516 options.data = 'data'; 28517 } 28518 if (this.useBlockParams) { 28519 options.blockParams = 'blockParams'; 28520 } 28521 return options; 28522 }, 28523 28524 setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { 28525 var options = this.setupParams(helper, paramSize, params); 28526 options
vendor: 1,005 bytes, lines 28526-28549
28526 = this.objectLiteral(options); 28527 if (useRegister) { 28528 this.useRegister('options'); 28529 params.push('options'); 28530 return ['options=', options]; 28531 } else if (params) { 28532 params.push(options); 28533 return ''; 28534 } else { 28535 return options; 28536 } 28537 } 28538 }; 28539 28540 (function () { 28541 var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); 28542 28543 var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; 28544 28545 for (var i = 0, l = reservedWords.length; i < l; i++) { 28546 compilerWords[reservedWords[i]] = true; 28547 } 28548 })(); 28549
vendor: 4,122 bytes, lines 28550-28701
28550 JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { 28551 return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); 28552 }; 28553 28554 function strictLookup(requireTerminal, compiler, parts, type) { 28555 var stack = compiler.popStack(), 28556 i = 0, 28557 len = parts.length; 28558 if (requireTerminal) { 28559 len--; 28560 } 28561 28562 for (; i < len; i++) { 28563 stack = compiler.nameLookup(stack, parts[i], type); 28564 } 28565 28566 if (requireTerminal) { 28567 return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')']; 28568 } else { 28569 return stack; 28570 } 28571 } 28572 28573 exports['default'] = JavaScriptCompiler; 28574 module.exports = exports['default']; 28575 28576/***/ }), 28577/* 43 */ 28578/***/ (function(module, exports, __webpack_require__) { 28579 28580 /* global define */ 28581 'use strict'; 28582 28583 exports.__esModule = true; 28584 28585 var _utils = __webpack_require__(5); 28586 28587 var SourceNode = undefined; 28588 28589 try { 28590 /* istanbul ignore next */ 28591 if (false) { 28592 // We don't support this in AMD environments. For these environments, we asusme that 28593 // they are running on the browser and thus have no need for the source-map library. 28594 var SourceMap = require('source-map'); 28595 SourceNode = SourceMap.SourceNode; 28596 } 28597 } catch (err) {} 28598 /* NOP */ 28599 28600 /* istanbul ignore if: tested but not covered in istanbul due to dist build */ 28601 if (!SourceNode) { 28602 SourceNode = function (line, column, srcFile, chunks) { 28603 this.src = ''; 28604 if (chunks) { 28605 this.add(chunks); 28606 } 28607 }; 28608 /* istanbul ignore next */ 28609 SourceNode.prototype = { 28610 add: function add(chunks) { 28611 if (_utils.isArray(chunks)) { 28612 chunks = chunks.join(''); 28613 } 28614 this.src += chunks; 28615 }, 28616 prepend: function prepend(chunks) { 28617 if (_utils.isArray(chunks)) { 28618 chunks = chunks.join(''); 28619 } 28620 this.src = chunks + this.src; 28621 }, 28622 toStringWithSourceMap: function toStringWithSourceMap() { 28623 return { code: this.toString() }; 28624 }, 28625 toString: function toString() { 28626 return this.src; 28627 } 28628 }; 28629 } 28630 28631 function castChunk(chunk, codeGen, loc) { 28632 if (_utils.isArray(chunk)) { 28633 var ret = []; 28634 28635 for (var i = 0, len = chunk.length; i < len; i++) { 28636 ret.push(codeGen.wrap(chunk[i], loc)); 28637 } 28638 return ret; 28639 } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { 28640 // Handle primitives that the SourceNode will throw up on 28641 return chunk + ''; 28642 } 28643 return chunk; 28644 } 28645 28646 function CodeGen(srcFile) { 28647 this.srcFile = srcFile; 28648 this.source = []; 28649 } 28650 28651 CodeGen.prototype = { 28652 isEmpty: function isEmpty() { 28653 return !this.source.length; 28654 }, 28655 prepend: function prepend(source, loc) { 28656 this.source.unshift(this.wrap(source, loc)); 28657 }, 28658 push: function push(source, loc) { 28659 this.source.push(this.wrap(source, loc)); 28660 }, 28661 28662 merge: function merge() { 28663 var source = this.empty(); 28664 this.each(function (line) { 28665 source.add([' ', line, '\n']); 28666 }); 28667 return source; 28668 }, 28669 28670 each: function each(iter) { 28671 for (var i = 0, len = this.source.length; i < len; i++) { 28672 iter(this.source[i]); 28673 } 28674 }, 28675 28676 empty: function empty() { 28677 var loc = this.currentLocation || { start: {} }; 28678 return new SourceNode(loc.start.line, loc.start.column, this.srcFile); 28679 }, 28680 wrap: function wrap(chunk) { 28681 var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; 28682 28683 if (chunk instanceof SourceNode) { 28684 return chunk; 28685 } 28686 28687 chunk = castChunk(chunk, this, loc); 28688 28689 return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); 28690 }, 28691 28692 functionCall: function functionCall(fn, type, params) { 28693 params = this.generateList(params); 28694 return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); 28695 }, 28696 28697 quotedString: function quotedString(str) { 28698 return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 28699 .replace(/\u2029/g, '\\u2029') + '"'; 28700 }, 28701
28702 objectLiteral: function objectLiteral(obj) { 28703 var pairs = []; 28704 28705 for (var key in obj) { 28706 if (obj.hasOwnProperty(key)) { 28707 var value = castChunk(obj[key], this); 28708 if (value !== 'undefined') { 28709 pairs.push([this.quotedString(key), ':', value]); 28710 } 28711 } 28712 } 28713 28714 var ret = this.generateList(pairs); 28715 ret.prepend('{'); 28716 ret.add('}'); 28717 return ret; 28718 }, 28719 28720 generateList: function generateList(entries) { 28721 var ret = this.empty(); 28722 28723 for (var i = 0, len = entries.length; i < len; i++) { 28724 if (i) { 28725 ret.add(','); 28726 } 28727 28728 ret.add(castChunk(entries[i], this)); 28729 } 28730 28731 return ret; 28732 }, 28733 28734 generateArray: function generateArray(entries) { 28735 var ret = this.generateList(entries); 28736 ret.prepend('['); 28737 ret.add(']'); 28738 28739 return ret; 28740 } 28741 }; 28742 28743 exports['default'] = CodeGen; 28744 module.exports = exports['default']; 28745 28746/***/ }) 28747/******/ ]) 28748}); 28749; 28750/*! 28751* jquery.inputmask.bundle.js 28752* https://github.com/RobinHerbots/Inputmask 28753* Copyright (c) 2010 - 2019 Robin Herbots 28754* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php) 28755* Version: 4.0.8 28756*/ 28757 28758(function(modules) { 28759 var installedModules = {}; 28760 function __webpack_require__(moduleId) { 28761 if (installedModules[moduleId]) { 28762 return installedModules[moduleId].exports; 28763 } 28764 var module = installedModules[moduleId] = { 28765 i: moduleId, 28766 l: false, 28767 exports: {} 28768 }; 28769 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 28770 module.l = true; 28771 return module.exports; 28772 } 28773 __webpack_require__.m = modules; 28774 __webpack_require__.c = installedModules; 28775 __webpack_require__.d = function(exports, name, getter) { 28776 if (!__webpack_require__.o(exports, name)) { 28777 Object.defineProperty(exports, name, { 28778 enumerable: true, 28779 get: getter 28780 }); 28781 } 28782 }; 28783 __webpack_require__.r = function(exports) { 28784 if (typeof Symbol !== "undefined" && Symbol.toStringTag) { 28785 Object.defineProperty(exports, Symbol.toStringTag, { 28786 value: "Module" 28787 }); 28788 } 28789 Object.defineProperty(exports, "__esModule", { 28790 value: true 28791 }); 28792 }; 28793 __webpack_require__.t = function(value, mode) { 28794 if (mode & 1) value = __webpack_require__(value); 28795 if (mode & 8) return value; 28796 if (mode & 4 && typeof value === "object" && value && value.__esModule) return value; 28797 var ns = Object.create(null); 28798 __webpack_require__.r(ns); 28799 Object.defineProperty(ns, "default", { 28800 enumerable: true, 28801 value: value 28802 }); 28803 if (mode & 2 && typeof value != "string") for (var key in value) __webpack_require__.d(ns, key, function(key) { 28804 return value[key]; 28805 }.bind(null, key)); 28806 return ns; 28807 }; 28808 __webpack_require__.n = function(module) { 28809 var getter = module && module.__esModule ? function getDefault() { 28810 return module["default"]; 28811 } : function getModuleExports() { 28812 return module; 28813 }; 28814 __webpack_require__.d(getter, "a", getter); 28815 return getter; 28816 }; 28817 __webpack_require__.o = function(object, property) { 28818 return Object.prototype.hasOwnProperty.call(object, property); 28819 }; 28820 __webpack_require__.p = ""; 28821 return __webpack_require__(__webpack_require__.s = 0); 28822})([ function(module, exports, __webpack_require__) { 28823 "use strict"; 28824 __webpack_require__(1); 28825 __webpack_require__(6); 28826 __webpack_require__(7); 28827 var _inputmask = __webpack_require__(2); 28828 var _inputmask2 = _interopRequireDefault(_inputmask); 28829 var _inputmask3 = __webpack_require__(3); 28830 var _inputmask4 = _interopRequireDefault(_inputmask3); 28831 var _jquery = __webpack_require__(4); 28832 var _jquery2 = _interopRequireDefault(_jquery); 28833 function _interopRequireDefault(obj) { 28834 return obj && obj.__esModule ? obj : { 28835 default: obj 28836 }; 28837 } 28838 if (_inputmask4.default === _jquery2.default) { 28839 __webpack_require__(8); 28840 } 28841 window.Inputmask = _inputmask2.default; 28842}, function(module, exports, __webpack_require__) { 28843 "use strict"; 28844 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 28845 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 28846 return typeof obj; 28847 } : function(obj) { 28848 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 28849 }; 28850 (function(factory) { 28851 if (true) { 28852 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 28853 __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 28854 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 28855 } else {} 28856 })(function(Inputmask) { 28857 Inputmask.extendDefinitions({ 28858 A: { 28859 validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]", 28860 casing: "upper" 28861 }, 28862 "&": { 28863 validator: "[0-9A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]", 28864 casing: "upper" 28865 }, 28866 "#": { 28867 validator: "[0-9A-Fa-f]", 28868 casing: "upper" 28869 } 28870 }); 28871 Inputmask.extendAliases({ 28872 cssunit: { 28873 regex: "[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)" 28874 }, 28875 url: { 28876 regex: "(https?|ftp)//.*", 28877 autoUnmask: false 28878 }, 28879 ip: { 28880 mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]", 28881 definitions: { 28882 i: { 28883 validator: function validator(chrs, maskset, pos, strict, opts) { 28884 if (pos - 1 > -1 && maskset.buffer[pos - 1] !== ".") { 28885 chrs = maskset.buffer[pos - 1] + chrs; 28886 if (pos - 2 > -1 && maskset.buffer[pos - 2] !== ".") { 28887 chrs = maskset.buffer[pos - 2] + chrs; 28888 } else chrs = "0" + chrs; 28889 } else chrs = "00" + chrs; 28890 return new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs); 28891 } 28892 } 28893 }, 28894 onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) { 28895 return maskedValue; 28896 }, 28897 inputmode: "numeric" 28898 }, 28899 email: { 28900 mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",
28901 greedy: false, 28902 casing: "lower", 28903 onBeforePaste: function onBeforePaste(pastedValue, opts) { 28904 pastedValue = pastedValue.toLowerCase(); 28905 return pastedValue.replace("mailto:", ""); 28906 }, 28907 definitions: { 28908 "*": { 28909 validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5!#$%&'*+/=?^_`{|}~-]" 28910 }, 28911 "-": { 28912 validator: "[0-9A-Za-z-]" 28913 } 28914 }, 28915 onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) { 28916 return maskedValue; 28917 }, 28918 inputmode: "email" 28919 }, 28920 mac: { 28921 mask: "##:##:##:##:##:##" 28922 }, 28923 vin: { 28924 mask: "V{13}9{4}", 28925 definitions: { 28926 V: { 28927 validator: "[A-HJ-NPR-Za-hj-npr-z\\d]", 28928 casing: "upper" 28929 } 28930 }, 28931 clearIncomplete: true, 28932 autoUnmask: true 28933 } 28934 }); 28935 return Inputmask; 28936 }); 28937}, function(module, exports, __webpack_require__) { 28938 "use strict"; 28939 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 28940 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 28941 return typeof obj; 28942 } : function(obj) { 28943 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 28944 }; 28945 (function(factory) { 28946 if (true) { 28947 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(3), __webpack_require__(5) ], 28948 __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 28949 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 28950 } else {} 28951 })(function($, window, undefined) { 28952 var document = window.document, ua = navigator.userAgent, ie = ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0, mobile = isInputEventSupported("touchstart"), iemobile = /iemobile/i.test(ua), iphone = /iphone/i.test(ua) && !iemobile; 28953 function Inputmask(alias, options, internal) { 28954 if (!(this instanceof Inputmask)) { 28955 return new Inputmask(alias, options, internal); 28956 } 28957 this.el = undefined; 28958 this.events = {}; 28959 this.maskset = undefined; 28960 this.refreshValue = false; 28961 if (internal !== true) { 28962 if ($.isPlainObject(alias)) { 28963 options = alias; 28964 } else { 28965 options = options || {}; 28966 if (alias) options.alias = alias; 28967 } 28968 this.opts = $.extend(true, {}, this.defaults, options); 28969 this.noMasksCache = options && options.definitions !== undefined; 28970 this.userOptions = options || {}; 28971 this.isRTL = this.opts.numericInput; 28972 resolveAlias(this.opts.alias, options, this.opts); 28973 } 28974 } 28975 Inputmask.prototype = { 28976 dataAttribute: "data-inputmask", 28977 defaults: { 28978 placeholder: "_", 28979 optionalmarker: [ "[", "]" ], 28980 quantifiermarker: [ "{", "}" ], 28981 groupmarker: [ "(", ")" ], 28982 alternatormarker: "|", 28983 escapeChar: "\\", 28984 mask: null, 28985 regex: null, 28986 oncomplete: $.noop, 28987 onincomplete: $.noop, 28988 oncleared: $.noop, 28989 repeat: 0, 28990 greedy: false, 28991 autoUnmask: false, 28992 removeMaskOnSubmit: false, 28993 clearMaskOnLostFocus: true, 28994 insertMode: true, 28995 clearIncomplete: false, 28996 alias: null, 28997 onKeyDown: $.noop, 28998 onBeforeMask: null, 28999 onBeforePaste: function onBeforePaste(pastedValue, opts) { 29000 return $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(this, pastedValue, opts) : pastedValue; 29001 }, 29002 onBeforeWrite: null, 29003 onUnMask: null, 29004 showMaskOnFocus: true, 29005 showMaskOnHover: true, 29006 onKeyValidation: $.noop, 29007 skipOptionalPartCharacter: " ", 29008 numericInput: false, 29009 rightAlign: false, 29010 undoOnEscape: true, 29011 radixPoint: "", 29012 _radixDance: false, 29013 groupSeparator: "", 29014 keepStatic: null, 29015 positionCaretOnTab: true, 29016 tabThrough: false, 29017 supportsInputType: [ "text", "tel", "url", "password", "search" ], 29018 ignorables: [ 8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 229 ], 29019 isComplete: null, 29020 preValidation: null, 29021 postValidation: null, 29022 staticDefinitionSymbol: undefined, 29023 jitMasking: false, 29024 nullable: true, 29025 inputEventOnly: false, 29026 noValuePatching: false, 29027 positionCaretOnClick: "lvp", 29028 casing: null, 29029 inputmode: "verbatim", 29030 colorMask: false, 29031 disablePredictiveText: false, 29032 importDataAttributes: true, 29033 shiftPositions: true 29034 }, 29035 definitions: { 29036 9: { 29037 validator: "[0-9\uff11-\uff19]", 29038 definitionSymbol: "*" 29039 }, 29040 a: { 29041 validator: "[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]", 29042 definitionSymbol: "*" 29043 }, 29044 "*": { 29045 validator: "[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]" 29046 } 29047 }, 29048 aliases: {}, 29049 masksCache: {}, 29050 mask: function mask(elems) { 29051 var that = this; 29052 function importAttributeOptions(npt, opts, userOptions, dataAttribute) { 29053 if (opts.importDataAttributes === true) { 29054 var attrOptions = npt.getAttribute(dataAttribute), option, dataoptions, optionData, p; 29055 var importOption = function importOption(option, optionData) { 29056 optionData = optionData !== undefined ? optionData : npt.getAttribute(dataAttribute + "-" + option); 29057 if (optionData !== null) { 29058 if (typeof optionData === "string") { 29059 if (option.indexOf("on") === 0) optionData = window[optionData];
29059 else if (optionData === "false") optionData = false; else if (optionData === "true") optionData = true; 29060 } 29061 userOptions[option] = optionData; 29062 } 29063 }; 29064 if (attrOptions && attrOptions !== "") { 29065 attrOptions = attrOptions.replace(/'/g, '"'); 29066 dataoptions = JSON.parse("{" + attrOptions + "}"); 29067 } 29068 if (dataoptions) { 29069 optionData = undefined; 29070 for (p in dataoptions) { 29071 if (p.toLowerCase() === "alias") { 29072 optionData = dataoptions[p]; 29073 break; 29074 } 29075 } 29076 } 29077 importOption("alias", optionData); 29078 if (userOptions.alias) { 29079 resolveAlias(userOptions.alias, userOptions, opts); 29080 } 29081 for (option in opts) { 29082 if (dataoptions) { 29083 optionData = undefined; 29084 for (p in dataoptions) { 29085 if (p.toLowerCase() === option.toLowerCase()) { 29086 optionData = dataoptions[p]; 29087 break; 29088 } 29089 } 29090 } 29091 importOption(option, optionData); 29092 } 29093 } 29094 $.extend(true, opts, userOptions); 29095 if (npt.dir === "rtl" || opts.rightAlign) { 29096 npt.style.textAlign = "right"; 29097 } 29098 if (npt.dir === "rtl" || opts.numericInput) { 29099 npt.dir = "ltr"; 29100 npt.removeAttribute("dir"); 29101 opts.isRTL = true; 29102 } 29103 return Object.keys(userOptions).length; 29104 } 29105 if (typeof elems === "string") { 29106 elems = document.getElementById(elems) || document.querySelectorAll(elems); 29107 } 29108 elems = elems.nodeName ? [ elems ] : elems; 29109 $.each(elems, function(ndx, el) { 29110 var scopedOpts = $.extend(true, {}, that.opts); 29111 if (importAttributeOptions(el, scopedOpts, $.extend(true, {}, that.userOptions), that.dataAttribute)) { 29112 var maskset = generateMaskSet(scopedOpts, that.noMasksCache); 29113 if (maskset !== undefined) { 29114 if (el.inputmask !== undefined) { 29115 el.inputmask.opts.autoUnmask = true; 29116 el.inputmask.remove(); 29117 } 29118 el.inputmask = new Inputmask(undefined, undefined, true); 29119 el.inputmask.opts = scopedOpts; 29120 el.inputmask.noMasksCache = that.noMasksCache; 29121 el.inputmask.userOptions = $.extend(true, {}, that.userOptions); 29122 el.inputmask.isRTL = scopedOpts.isRTL || scopedOpts.numericInput; 29123 el.inputmask.el = el; 29124 el.inputmask.maskset = maskset; 29125 $.data(el, "_inputmask_opts", scopedOpts); 29126 maskScope.call(el.inputmask, { 29127 action: "mask" 29128 }); 29129 } 29130 } 29131 }); 29132 return elems && elems[0] ? elems[0].inputmask || this : this; 29133 }, 29134 option: function option(options, noremask) { 29135 if (typeof options === "string") { 29136 return this.opts[options]; 29137 } else if ((typeof options === "undefined" ? "undefined" : _typeof(options)) === "object") { 29138 $.extend(this.userOptions, options); 29139 if (this.el && noremask !== true) { 29140 this.mask(this.el); 29141 } 29142 return this; 29143 } 29144 }, 29145 unmaskedvalue: function unmaskedvalue(value) { 29146 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29147 return maskScope.call(this, { 29148 action: "unmaskedvalue", 29149 value: value 29150 }); 29151 }, 29152 remove: function remove() { 29153 return maskScope.call(this, { 29154 action: "remove" 29155 }); 29156 }, 29157 getemptymask: function getemptymask() { 29158 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29159 return maskScope.call(this, { 29160 action: "getemptymask" 29161 }); 29162 }, 29163 hasMaskedValue: function hasMaskedValue() { 29164 return !this.opts.autoUnmask; 29165 }, 29166 isComplete: function isComplete() { 29167 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29168 return maskScope.call(this, { 29169 action: "isComplete" 29170 }); 29171 }, 29172 getmetadata: function getmetadata() { 29173 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29174 return maskScope.call(this, { 29175 action: "getmetadata" 29176 }); 29177 }, 29178 isValid: function isValid(value) { 29179 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29180 return maskScope.call(this, { 29181 action: "isValid", 29182 value: value 29183 }); 29184 }, 29185 format: function format(value, metadata) { 29186 this.maskset = this.maskset || generateMaskSet(this.opts, this.noMasksCache); 29187 return maskScope.call(this, { 29188 action: "format", 29189 value: value, 29190 metadata: metadata 29191 }); 29192 }, 29193 setValue: function setValue(value) { 29194 if (this.el) { 29195 $(this.el).trigger("setvalue", [ value ]); 29196 } 29197 }, 29198 analyseMask: function analyseMask(mask, regexMask, opts) { 29199 var tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?(?:\|[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g, regexTokenizer = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, escaped = false, currentToken = new MaskToken(), match, m, openenings = [], maskTokens = [], openingToken, currentOpeningToken, alternator, lastMatch, groupToken; 29200 function MaskToken(isGroup, isOptional, isQuantifier, isAlternator) { 29201 this.matches = []; 29202 this.openGroup = isGroup || false; 29203 this.alternatorGroup = false;
29204 this.isGroup = isGroup || false; 29205 this.isOptional = isOptional || false; 29206 this.isQuantifier = isQuantifier || false; 29207 this.isAlternator = isAlternator || false; 29208 this.quantifier = { 29209 min: 1, 29210 max: 1 29211 }; 29212 } 29213 function insertTestDefinition(mtoken, element, position) { 29214 position = position !== undefined ? position : mtoken.matches.length; 29215 var prevMatch = mtoken.matches[position - 1]; 29216 if (regexMask) { 29217 if (element.indexOf("[") === 0 || escaped && /\\d|\\s|\\w]/i.test(element) || element === ".") { 29218 mtoken.matches.splice(position++, 0, { 29219 fn: new RegExp(element, opts.casing ? "i" : ""), 29220 optionality: false, 29221 newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element, 29222 casing: null, 29223 def: element, 29224 placeholder: undefined, 29225 nativeDef: element 29226 }); 29227 } else { 29228 if (escaped) element = element[element.length - 1]; 29229 $.each(element.split(""), function(ndx, lmnt) { 29230 prevMatch = mtoken.matches[position - 1]; 29231 mtoken.matches.splice(position++, 0, { 29232 fn: null, 29233 optionality: false, 29234 newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== lmnt && prevMatch.fn !== null, 29235 casing: null, 29236 def: opts.staticDefinitionSymbol || lmnt, 29237 placeholder: opts.staticDefinitionSymbol !== undefined ? lmnt : undefined, 29238 nativeDef: (escaped ? "'" : "") + lmnt 29239 }); 29240 }); 29241 } 29242 escaped = false; 29243 } else { 29244 var maskdef = (opts.definitions ? opts.definitions[element] : undefined) || Inputmask.prototype.definitions[element]; 29245 if (maskdef && !escaped) { 29246 mtoken.matches.splice(position++, 0, { 29247 fn: maskdef.validator ? typeof maskdef.validator == "string" ? new RegExp(maskdef.validator, opts.casing ? "i" : "") : new function() { 29248 this.test = maskdef.validator; 29249 }() : new RegExp("."), 29250 optionality: false, 29251 newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== (maskdef.definitionSymbol || element), 29252 casing: maskdef.casing, 29253 def: maskdef.definitionSymbol || element, 29254 placeholder: maskdef.placeholder, 29255 nativeDef: element 29256 }); 29257 } else { 29258 mtoken.matches.splice(position++, 0, { 29259 fn: null, 29260 optionality: false, 29261 newBlockMarker: prevMatch === undefined ? "master" : prevMatch.def !== element && prevMatch.fn !== null, 29262 casing: null, 29263 def: opts.staticDefinitionSymbol || element, 29264 placeholder: opts.staticDefinitionSymbol !== undefined ? element : undefined, 29265 nativeDef: (escaped ? "'" : "") + element 29266 }); 29267 escaped = false;
vendor: 5,552 bytes, lines 29268-29382
29268 } 29269 } 29270 } 29271 function verifyGroupMarker(maskToken) { 29272 if (maskToken && maskToken.matches) { 29273 $.each(maskToken.matches, function(ndx, token) { 29274 var nextToken = maskToken.matches[ndx + 1]; 29275 if ((nextToken === undefined || nextToken.matches === undefined || nextToken.isQuantifier === false) && token && token.isGroup) { 29276 token.isGroup = false; 29277 if (!regexMask) { 29278 insertTestDefinition(token, opts.groupmarker[0], 0); 29279 if (token.openGroup !== true) { 29280 insertTestDefinition(token, opts.groupmarker[1]); 29281 } 29282 } 29283 } 29284 verifyGroupMarker(token); 29285 }); 29286 } 29287 } 29288 function defaultCase() { 29289 if (openenings.length > 0) { 29290 currentOpeningToken = openenings[openenings.length - 1]; 29291 insertTestDefinition(currentOpeningToken, m); 29292 if (currentOpeningToken.isAlternator) { 29293 alternator = openenings.pop(); 29294 for (var mndx = 0; mndx < alternator.matches.length; mndx++) { 29295 if (alternator.matches[mndx].isGroup) alternator.matches[mndx].isGroup = false; 29296 } 29297 if (openenings.length > 0) { 29298 currentOpeningToken = openenings[openenings.length - 1]; 29299 currentOpeningToken.matches.push(alternator); 29300 } else { 29301 currentToken.matches.push(alternator); 29302 } 29303 } 29304 } else { 29305 insertTestDefinition(currentToken, m); 29306 } 29307 } 29308 function reverseTokens(maskToken) { 29309 function reverseStatic(st) { 29310 if (st === opts.optionalmarker[0]) st = opts.optionalmarker[1]; else if (st === opts.optionalmarker[1]) st = opts.optionalmarker[0]; else if (st === opts.groupmarker[0]) st = opts.groupmarker[1]; else if (st === opts.groupmarker[1]) st = opts.groupmarker[0]; 29311 return st; 29312 } 29313 maskToken.matches = maskToken.matches.reverse(); 29314 for (var match in maskToken.matches) { 29315 if (maskToken.matches.hasOwnProperty(match)) { 29316 var intMatch = parseInt(match); 29317 if (maskToken.matches[match].isQuantifier && maskToken.matches[intMatch + 1] && maskToken.matches[intMatch + 1].isGroup) { 29318 var qt = maskToken.matches[match]; 29319 maskToken.matches.splice(match, 1); 29320 maskToken.matches.splice(intMatch + 1, 0, qt); 29321 } 29322 if (maskToken.matches[match].matches !== undefined) { 29323 maskToken.matches[match] = reverseTokens(maskToken.matches[match]); 29324 } else { 29325 maskToken.matches[match] = reverseStatic(maskToken.matches[match]); 29326 } 29327 } 29328 } 29329 return maskToken; 29330 } 29331 function groupify(matches) { 29332 var groupToken = new MaskToken(true); 29333 groupToken.openGroup = false; 29334 groupToken.matches = matches; 29335 return groupToken; 29336 } 29337 if (regexMask) { 29338 opts.optionalmarker[0] = undefined; 29339 opts.optionalmarker[1] = undefined; 29340 } 29341 while (match = regexMask ? regexTokenizer.exec(mask) : tokenizer.exec(mask)) { 29342 m = match[0]; 29343 if (regexMask) { 29344 switch (m.charAt(0)) { 29345 case "?": 29346 m = "{0,1}"; 29347 break; 29348 29349 case "+": 29350 case "*": 29351 m = "{" + m + "}"; 29352 break; 29353 } 29354 } 29355 if (escaped) { 29356 defaultCase(); 29357 continue; 29358 } 29359 switch (m.charAt(0)) { 29360 case "(?=": 29361 break; 29362 29363 case "(?!": 29364 break; 29365 29366 case "(?<=": 29367 break; 29368 29369 case "(?<!": 29370 break; 29371 29372 case opts.escapeChar: 29373 escaped = true; 29374 if (regexMask) { 29375 defaultCase(); 29376 } 29377 break; 29378 29379 case opts.optionalmarker[1]: 29380 case opts.groupmarker[1]: 29381 openingToken = openenings.pop(); 29382 openingToken.openGroup = false;
29383 if (openingToken !== undefined) { 29384 if (openenings.length > 0) { 29385 currentOpeningToken = openenings[openenings.length - 1]; 29386 currentOpeningToken.matches.push(openingToken); 29387 if (currentOpeningToken.isAlternator) { 29388 alternator = openenings.pop(); 29389 for (var mndx = 0; mndx < alternator.matches.length; mndx++) { 29390 alternator.matches[mndx].isGroup = false; 29391 alternator.matches[mndx].alternatorGroup = false; 29392 } 29393 if (openenings.length > 0) { 29394 currentOpeningToken = openenings[openenings.length - 1]; 29395 currentOpeningToken.matches.push(alternator); 29396 } else { 29397 currentToken.matches.push(alternator); 29398 } 29399 } 29400 } else { 29401 currentToken.matches.push(openingToken); 29402 } 29403 } else defaultCase(); 29404 break; 29405 29406 case opts.optionalmarker[0]: 29407 openenings.push(new MaskToken(false, true)); 29408 break; 29409 29410 case opts.groupmarker[0]: 29411 openenings.push(new MaskToken(true)); 29412 break; 29413 29414 case opts.quantifiermarker[0]: 29415 var quantifier = new MaskToken(false, false, true); 29416 m = m.replace(/[{}]/g, ""); 29417 var mqj = m.split("|"), mq = mqj[0].split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = mq.length === 1 ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]); 29418 if (mq0 === "*" || mq0 === "+") { 29419 mq0 = mq1 === "*" ? 0 : 1; 29420 } 29421 quantifier.quantifier = { 29422 min: mq0, 29423 max: mq1, 29424 jit: mqj[1] 29425 }; 29426 var matches = openenings.length > 0 ? openenings[openenings.length - 1].matches : currentToken.matches; 29427 match = matches.pop(); 29428 if (match.isAlternator) { 29429 matches.push(match); 29430 matches = match.matches; 29431 var groupToken = new MaskToken(true); 29432 var tmpMatch = matches.pop(); 29433 matches.push(groupToken); 29434 matches = groupToken.matches; 29435 match = tmpMatch; 29436 } 29437 if (!match.isGroup) { 29438 match = groupify([ match ]); 29439 } 29440 matches.push(match); 29441 matches.push(quantifier); 29442 break; 29443 29444 case opts.alternatormarker: 29445 var groupQuantifier = function groupQuantifier(matches) { 29446 var lastMatch = matches.pop(); 29447 if (lastMatch.isQuantifier) { 29448 lastMatch = groupify([ matches.pop(), lastMatch ]); 29449 } 29450 return lastMatch; 29451 }; 29452 if (openenings.length > 0) { 29453 currentOpeningToken = openenings[openenings.length - 1]; 29454 var subToken = currentOpeningToken.matches[currentOpeningToken.matches.length - 1]; 29455 if (currentOpeningToken.openGroup && (subToken.matches === undefined || subToken.isGroup === false && subToken.isAlternator === false)) { 29456 lastMatch = openenings.pop(); 29457 } else { 29458 lastMatch = groupQuantifier(currentOpeningToken.matches); 29459 } 29460 } else { 29461 lastMatch = groupQuantifier(currentToken.matches); 29462 } 29463 if (lastMatch.isAlternator) { 29464 openenings.push(lastMatch); 29465 } else { 29466 if (lastMatch.alternatorGroup) { 29467 alternator = openenings.pop(); 29468 lastMatch.alternatorGroup = false;
29469 } else { 29470 alternator = new MaskToken(false, false, false, true); 29471 } 29472 alternator.matches.push(lastMatch); 29473 openenings.push(alternator); 29474 if (lastMatch.openGroup) { 29475 lastMatch.openGroup = false; 29476 var alternatorGroup = new MaskToken(true); 29477 alternatorGroup.alternatorGroup = true; 29478 openenings.push(alternatorGroup); 29479 } 29480 } 29481 break; 29482 29483 default: 29484 defaultCase(); 29485 } 29486 } 29487 while (openenings.length > 0) { 29488 openingToken = openenings.pop(); 29489 currentToken.matches.push(openingToken); 29490 } 29491 if (currentToken.matches.length > 0) { 29492 verifyGroupMarker(currentToken); 29493 maskTokens.push(currentToken); 29494 } 29495 if (opts.numericInput || opts.isRTL) { 29496 reverseTokens(maskTokens[0]); 29497 } 29498 return maskTokens; 29499 }, 29500 positionColorMask: function positionColorMask(input, template) { 29501 input.style.left = template.offsetLeft + "px"; 29502 } 29503 }; 29504 Inputmask.extendDefaults = function(options) { 29505 $.extend(true, Inputmask.prototype.defaults, options); 29506 }; 29507 Inputmask.extendDefinitions = function(definition) { 29508 $.extend(true, Inputmask.prototype.definitions, definition); 29509 }; 29510 Inputmask.extendAliases = function(alias) { 29511 $.extend(true, Inputmask.prototype.aliases, alias); 29512 }; 29513 Inputmask.format = function(value, options, metadata) { 29514 return Inputmask(options).format(value, metadata); 29515 }; 29516 Inputmask.unmask = function(value, options) { 29517 return Inputmask(options).unmaskedvalue(value); 29518 }; 29519 Inputmask.isValid = function(value, options) { 29520 return Inputmask(options).isValid(value); 29521 }; 29522 Inputmask.remove = function(elems) { 29523 if (typeof elems === "string") { 29524 elems = document.getElementById(elems) || document.querySelectorAll(elems); 29525 } 29526 elems = elems.nodeName ? [ elems ] : elems; 29527 $.each(elems, function(ndx, el) { 29528 if (el.inputmask) el.inputmask.remove(); 29529 }); 29530 }; 29531 Inputmask.setValue = function(elems, value) { 29532 if (typeof elems === "string") { 29533 elems = document.getElementById(elems) || document.querySelectorAll(elems); 29534 } 29535 elems = elems.nodeName ? [ elems ] : elems; 29536 $.each(elems, function(ndx, el) { 29537 if (el.inputmask) el.inputmask.setValue(value); else $(el).trigger("setvalue", [ value ]); 29538 }); 29539 }; 29540 Inputmask.escapeRegex = function(str) { 29541 var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ]; 29542 return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1"); 29543 }; 29544 Inputmask.keyCode = { 29545 BACKSPACE: 8, 29546 BACKSPACE_SAFARI: 127, 29547 DELETE: 46, 29548 DOWN: 40, 29549 END: 35, 29550 ENTER: 13, 29551 ESCAPE: 27, 29552 HOME: 36, 29553 INSERT: 45, 29554 LEFT: 37, 29555 PAGE_DOWN: 34, 29556 PAGE_UP: 33, 29557 RIGHT: 39, 29558 SPACE: 32, 29559 TAB: 9, 29560 UP: 38, 29561 X: 88, 29562 CONTROL: 17 29563 }; 29564 Inputmask.dependencyLib = $; 29565 function resolveAlias(aliasStr, options, opts) { 29566 var aliasDefinition = Inputmask.prototype.aliases[aliasStr]; 29567 if (aliasDefinition) { 29568 if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts); 29569 $.extend(true, opts, aliasDefinition); 29570 $.extend(true, opts, options); 29571 return true; 29572 } else if (opts.mask === null) { 29573 opts.mask = aliasStr; 29574 } 29575 return false;
29576 } 29577 function generateMaskSet(opts, nocache) { 29578 function generateMask(mask, metadata, opts) { 29579 var regexMask = false; 29580 if (mask === null || mask === "") { 29581 regexMask = opts.regex !== null; 29582 if (regexMask) { 29583 mask = opts.regex; 29584 mask = mask.replace(/^(\^)(.*)(\$)$/, "$2"); 29585 } else { 29586 regexMask = true; 29587 mask = ".*"; 29588 } 29589 } 29590 if (mask.length === 1 && opts.greedy === false && opts.repeat !== 0) { 29591 opts.placeholder = ""; 29592 } 29593 if (opts.repeat > 0 || opts.repeat === "*" || opts.repeat === "+") { 29594 var repeatStart = opts.repeat === "*" ? 0 : opts.repeat === "+" ? 1 : opts.repeat; 29595 mask = opts.groupmarker[0] + mask + opts.groupmarker[1] + opts.quantifiermarker[0] + repeatStart + "," + opts.repeat + opts.quantifiermarker[1]; 29596 } 29597 var masksetDefinition, maskdefKey = regexMask ? "regex_" + opts.regex : opts.numericInput ? mask.split("").reverse().join("") : mask; 29598 if (Inputmask.prototype.masksCache[maskdefKey] === undefined || nocache === true) { 29599 masksetDefinition = { 29600 mask: mask, 29601 maskToken: Inputmask.prototype.analyseMask(mask, regexMask, opts), 29602 validPositions: {}, 29603 _buffer: undefined, 29604 buffer: undefined, 29605 tests: {}, 29606 excludes: {}, 29607 metadata: metadata, 29608 maskLength: undefined, 29609 jitOffset: {} 29610 }; 29611 if (nocache !== true) { 29612 Inputmask.prototype.masksCache[maskdefKey] = masksetDefinition; 29613 masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]); 29614 } 29615 } else masksetDefinition = $.extend(true, {}, Inputmask.prototype.masksCache[maskdefKey]); 29616 return masksetDefinition; 29617 } 29618 var ms; 29619 if ($.isFunction(opts.mask)) { 29620 opts.mask = opts.mask(opts); 29621 } 29622 if ($.isArray(opts.mask)) { 29623 if (opts.mask.length > 1) { 29624 if (opts.keepStatic === null) { 29625 opts.keepStatic = "auto"; 29626 for (var i = 0; i < opts.mask.length; i++) { 29627 if (opts.mask[i].charAt(0) !== opts.mask[0].charAt(0)) { 29628 opts.keepStatic = true; 29629 break; 29630 } 29631 } 29632 } 29633 var altMask = opts.groupmarker[0]; 29634 $.each(opts.isRTL ? opts.mask.reverse() : opts.mask, function(ndx, msk) { 29635 if (altMask.length > 1) { 29636 altMask += opts.groupmarker[1] + opts.alternatormarker + opts.groupmarker[0]; 29637 } 29638 if (msk.mask !== undefined && !$.isFunction(msk.mask)) { 29639 altMask += msk.mask; 29640 } else { 29641 altMask += msk; 29642 } 29643 }); 29644 altMask += opts.groupmarker[1]; 29645 return generateMask(altMask, opts.mask, opts); 29646 } else opts.mask = opts.mask.pop(); 29647 } 29648 if (opts.mask && opts.mask.mask !== undefined && !$.isFunction(opts.mask.mask)) { 29649 ms = generateMask(opts.mask.mask, opts.mask, opts); 29650 } else { 29651 ms = generateMask(opts.mask, opts.mask, opts); 29652 } 29653 return ms; 29654 } 29655 function isInputEventSupported(eventName) { 29656 var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el; 29657 if (!isSupported) { 29658 el.setAttribute(evName, "return;"); 29659 isSupported = typeof el[evName] === "function"; 29660 } 29661 el = null; 29662 return isSupported; 29663 } 29664 function maskScope(actionObj, maskset, opts) { 29665 maskset = maskset || this.maskset; 29666 opts = opts || this.opts; 29667 var inputmask = this, el = this.el, isRTL = this.isRTL, undoValue, $el, skipKeyPressEvent = false, skipInputEvent = false, ignorable = false, maxLength, mouseEnter = false, colorMask, originalPlaceholder; 29668 var getMaskTemplate = function getMaskTemplate(baseOnInput, minimalPos, includeMode, noJit, clearOptionalTail) { 29669 var greedy = opts.greedy; 29670 if (clearOptionalTail) opts.greedy = false;
29671 minimalPos = minimalPos || 0; 29672 var maskTemplate = [], ndxIntlzr, pos = 0, test, testPos, lvp = getLastValidPosition(); 29673 do { 29674 if (baseOnInput === true && getMaskSet().validPositions[pos]) { 29675 testPos = clearOptionalTail && getMaskSet().validPositions[pos].match.optionality === true && getMaskSet().validPositions[pos + 1] === undefined && (getMaskSet().validPositions[pos].generatedInput === true || getMaskSet().validPositions[pos].input == opts.skipOptionalPartCharacter && pos > 0) ? determineTestTemplate(pos, getTests(pos, ndxIntlzr, pos - 1)) : getMaskSet().validPositions[pos]; 29676 test = testPos.match; 29677 ndxIntlzr = testPos.locator.slice(); 29678 maskTemplate.push(includeMode === true ? testPos.input : includeMode === false ? test.nativeDef : getPlaceholder(pos, test)); 29679 } else { 29680 testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); 29681 test = testPos.match; 29682 ndxIntlzr = testPos.locator.slice(); 29683 var jitMasking = noJit === true ? false : opts.jitMasking !== false ? opts.jitMasking : test.jit; 29684 if (jitMasking === false || jitMasking === undefined || typeof jitMasking === "number" && isFinite(jitMasking) && jitMasking > pos) { 29685 maskTemplate.push(includeMode === false ? test.nativeDef : getPlaceholder(pos, test)); 29686 } 29687 } 29688 if (opts.keepStatic === "auto") { 29689 if (test.newBlockMarker && test.fn !== null) { 29690 opts.keepStatic = pos - 1; 29691 } 29692 } 29693 pos++; 29694 } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || minimalPos > pos); 29695 if (maskTemplate[maskTemplate.length - 1] === "") { 29696 maskTemplate.pop(); 29697 } 29698 if (includeMode !== false || getMaskSet().maskLength === undefined) getMaskSet().maskLength = pos - 1; 29699 opts.greedy = greedy; 29700 return maskTemplate; 29701 }; 29702 function getMaskSet() { 29703 return maskset; 29704 } 29705 function resetMaskSet(soft) { 29706 var maskset = getMaskSet(); 29707 maskset.buffer = undefined; 29708 if (soft !== true) { 29709 maskset.validPositions = {}; 29710 maskset.p = 0; 29711 } 29712 } 29713 function getLastValidPosition(closestTo, strict, validPositions) { 29714 var before = -1, after = -1, valids = validPositions || getMaskSet().validPositions; 29715 if (closestTo === undefined) closestTo = -1; 29716 for (var posNdx in valids) { 29717 var psNdx = parseInt(posNdx); 29718 if (valids[psNdx] && (strict || valids[psNdx].generatedInput !== true)) { 29719 if (psNdx <= closestTo) before = psNdx; 29720 if (psNdx >= closestTo) after = psNdx; 29721 } 29722 } 29723 return before === -1 || before == closestTo ? after : after == -1 ? before : closestTo - before < after - closestTo ? before : after; 29724 } 29725 function getDecisionTaker(tst) { 29726 var decisionTaker = tst.locator[tst.alternation]; 29727 if (typeof decisionTaker == "string" && decisionTaker.length > 0) { 29728 decisionTaker = decisionTaker.split(",")[0]; 29729 } 29730 return decisionTaker !== undefined ? decisionTaker.toString() : ""; 29731 } 29732 function getLocator(tst, align) { 29733 var locator = (tst.alternation != undefined ? tst.mloc[getDecisionTaker(tst)] : tst.locator).join(""); 29734 if (locator !== "") while (locator.length < align) { 29735 locator += "0"; 29736 } 29737 return locator; 29738 } 29739 function determineTestTemplate(pos, tests) { 29740 pos = pos > 0 ? pos - 1 : 0;
29741 var altTest = getTest(pos), targetLocator = getLocator(altTest), tstLocator, closest, bestMatch; 29742 for (var ndx = 0; ndx < tests.length; ndx++) { 29743 var tst = tests[ndx]; 29744 tstLocator = getLocator(tst, targetLocator.length); 29745 var distance = Math.abs(tstLocator - targetLocator); 29746 if (closest === undefined || tstLocator !== "" && distance < closest || bestMatch && !opts.greedy && bestMatch.match.optionality && bestMatch.match.newBlockMarker === "master" && (!tst.match.optionality || !tst.match.newBlockMarker) || bestMatch && bestMatch.match.optionalQuantifier && !tst.match.optionalQuantifier) { 29747 closest = distance; 29748 bestMatch = tst; 29749 } 29750 } 29751 return bestMatch; 29752 } 29753 function getTestTemplate(pos, ndxIntlzr, tstPs) { 29754 return getMaskSet().validPositions[pos] || determineTestTemplate(pos, getTests(pos, ndxIntlzr ? ndxIntlzr.slice() : ndxIntlzr, tstPs)); 29755 } 29756 function getTest(pos, tests) { 29757 if (getMaskSet().validPositions[pos]) { 29758 return getMaskSet().validPositions[pos]; 29759 } 29760 return (tests || getTests(pos))[0]; 29761 } 29762 function positionCanMatchDefinition(pos, def) { 29763 var valid = false, tests = getTests(pos); 29764 for (var tndx = 0; tndx < tests.length; tndx++) { 29765 if (tests[tndx].match && tests[tndx].match.def === def) { 29766 valid = true; 29767 break; 29768 } 29769 } 29770 return valid; 29771 } 29772 function getTests(pos, ndxIntlzr, tstPs) { 29773 var maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr ? ndxIntlzr.slice() : [ 0 ], matches = [], insertStop = false, latestMatch, cacheDependency = ndxIntlzr ? ndxIntlzr.join("") : ""; 29774 function resolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) { 29775 function handleMatch(match, loopNdx, quantifierRecurse) { 29776 function isFirstMatch(latestMatch, tokenGroup) { 29777 var firstMatch = $.inArray(latestMatch, tokenGroup.matches) === 0; 29778 if (!firstMatch) { 29779 $.each(tokenGroup.matches, function(ndx, match) { 29780 if (match.isQuantifier === true) firstMatch = isFirstMatch(latestMatch, tokenGroup.matches[ndx - 1]); else if (match.hasOwnProperty("matches")) firstMatch = isFirstMatch(latestMatch, match); 29781 if (firstMatch) return false; 29782 }); 29783 } 29784 return firstMatch; 29785 } 29786 function resolveNdxInitializer(pos, alternateNdx, targetAlternation) { 29787 var bestMatch, indexPos; 29788 if (getMaskSet().tests[pos] || getMaskSet().validPositions[pos]) { 29789 $.each(getMaskSet().tests[pos] || [ getMaskSet().validPositions[pos] ], function(ndx, lmnt) { 29790 if (lmnt.mloc[alternateNdx]) { 29791 bestMatch = lmnt; 29792 return false; 29793 } 29794 var alternation = targetAlternation !== undefined ? targetAlternation : lmnt.alternation, ndxPos = lmnt.locator[alternation] !== undefined ? lmnt.locator[alternation].toString().indexOf(alternateNdx) : -1; 29795 if ((indexPos === undefined || ndxPos < indexPos) && ndxPos !== -1) { 29796 bestMatch = lmnt; 29797 indexPos = ndxPos; 29798 } 29799 }); 29800 } 29801 if (bestMatch) { 29802 var bestMatchAltIndex = bestMatch.locator[bestMatch.alternation]; 29803 var locator = bestMatch.mloc[alternateNdx] || bestMatch.mloc[bestMatchAltIndex] || bestMatch.locator; 29804 return locator.slice((targetAlternation !== undefined ? targetAlternation : bestMatch.alternation) + 1); 29805 } else { 29806 return targetAlternation !== undefined ? resolveNdxInitializer(pos, alternateNdx) : undefined; 29807 } 29808 } 29809 function isSubsetOf(source, target) { 29810 function expand(pattern) { 29811 var expanded = [], start, end; 29812 for (var i = 0, l = pattern.length; i < l; i++) { 29813 if (pattern.charAt(i) === "-") {
29814 end = pattern.charCodeAt(i + 1); 29815 while (++start < end) { 29816 expanded.push(String.fromCharCode(start)); 29817 } 29818 } else { 29819 start = pattern.charCodeAt(i); 29820 expanded.push(pattern.charAt(i)); 29821 } 29822 } 29823 return expanded.join(""); 29824 } 29825 if (opts.regex && source.match.fn !== null && target.match.fn !== null) { 29826 return expand(target.match.def.replace(/[\[\]]/g, "")).indexOf(expand(source.match.def.replace(/[\[\]]/g, ""))) !== -1; 29827 } 29828 return source.match.def === target.match.nativeDef; 29829 } 29830 function staticCanMatchDefinition(source, target) { 29831 var sloc = source.locator.slice(source.alternation).join(""), tloc = target.locator.slice(target.alternation).join(""), canMatch = sloc == tloc; 29832 canMatch = canMatch && source.match.fn === null && target.match.fn !== null ? target.match.fn.test(source.match.def, getMaskSet(), pos, false, opts, false) : false; 29833 return canMatch; 29834 } 29835 function setMergeLocators(targetMatch, altMatch) { 29836 if (altMatch === undefined || targetMatch.alternation === altMatch.alternation && targetMatch.locator[targetMatch.alternation].toString().indexOf(altMatch.locator[altMatch.alternation]) === -1) { 29837 targetMatch.mloc = targetMatch.mloc || {}; 29838 var locNdx = targetMatch.locator[targetMatch.alternation]; 29839 if (locNdx === undefined) targetMatch.alternation = undefined; else { 29840 if (typeof locNdx === "string") locNdx = locNdx.split(",")[0]; 29841 if (targetMatch.mloc[locNdx] === undefined) targetMatch.mloc[locNdx] = targetMatch.locator.slice(); 29842 if (altMatch !== undefined) { 29843 for (var ndx in altMatch.mloc) { 29844 if (typeof ndx === "string") ndx = ndx.split(",")[0]; 29845 if (targetMatch.mloc[ndx] === undefined) targetMatch.mloc[ndx] = altMatch.mloc[ndx]; 29846 } 29847 targetMatch.locator[targetMatch.alternation] = Object.keys(targetMatch.mloc).join(","); 29848 } 29849 return true; 29850 } 29851 } 29852 return false; 29853 } 29854 if (testPos > 500 && quantifierRecurse !== undefined) { 29855 throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet().mask; 29856 } 29857 if (testPos === pos && match.matches === undefined) { 29858 matches.push({ 29859 match: match, 29860 locator: loopNdx.reverse(), 29861 cd: cacheDependency, 29862 mloc: {} 29863 }); 29864 return true; 29865 } else if (match.matches !== undefined) { 29866 if (match.isGroup && quantifierRecurse !== match) { 29867 match = handleMatch(maskToken.matches[$.inArray(match, maskToken.matches) + 1], loopNdx, quantifierRecurse); 29868 if (match) return true; 29869 } else if (match.isOptional) { 29870 var optionalToken = match; 29871 match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse); 29872 if (match) { 29873 $.each(matches, function(ndx, mtch) { 29874 mtch.match.optionality = true; 29875 }); 29876 latestMatch = matches[matches.length - 1].match; 29877 if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) { 29878 insertStop = true; 29879 testPos = pos; 29880 } else return true; 29881 } 29882 } else if (match.isAlternator) { 29883 var alternateToken = match, malternateMatches = [], maltMatches, currentMatches = matches.slice(), loopNdxCnt = loopNdx.length; 29884 var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1; 29885 if (altIndex === -1 || typeof altIndex === "string") { 29886 var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [], amndx; 29887 if (typeof altIndex == "string") { 29888 altIndexArr = altIndex.split(","); 29889 } else { 29890 for (amndx = 0;
29890 amndx < alternateToken.matches.length; amndx++) { 29891 altIndexArr.push(amndx.toString()); 29892 } 29893 } 29894 if (getMaskSet().excludes[pos]) { 29895 var altIndexArrClone = altIndexArr.slice(); 29896 for (var i = 0, el = getMaskSet().excludes[pos].length; i < el; i++) { 29897 altIndexArr.splice(altIndexArr.indexOf(getMaskSet().excludes[pos][i].toString()), 1); 29898 } 29899 if (altIndexArr.length === 0) { 29900 getMaskSet().excludes[pos] = undefined; 29901 altIndexArr = altIndexArrClone; 29902 } 29903 } 29904 if (opts.keepStatic === true || isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic) altIndexArr = altIndexArr.slice(0, 1); 29905 var unMatchedAlternation = false; 29906 for (var ndx = 0; ndx < altIndexArr.length; ndx++) { 29907 amndx = parseInt(altIndexArr[ndx]); 29908 matches = []; 29909 ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice(); 29910 if (alternateToken.matches[amndx] && handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse)) match = true; else if (ndx === 0) { 29911 unMatchedAlternation = true; 29912 } 29913 maltMatches = matches.slice(); 29914 testPos = currentPos; 29915 matches = []; 29916 for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) { 29917 var altMatch = maltMatches[ndx1], dropMatch = false; 29918 altMatch.match.jit = altMatch.match.jit || unMatchedAlternation; 29919 altMatch.alternation = altMatch.alternation || loopNdxCnt; 29920 setMergeLocators(altMatch); 29921 for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) { 29922 var altMatch2 = malternateMatches[ndx2]; 29923 if (typeof altIndex !== "string" || altMatch.alternation !== undefined && $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr) !== -1) { 29924 if (altMatch.match.nativeDef === altMatch2.match.nativeDef) { 29925 dropMatch = true; 29926 setMergeLocators(altMatch2, altMatch); 29927 break; 29928 } else if (isSubsetOf(altMatch, altMatch2)) { 29929 if (setMergeLocators(altMatch, altMatch2)) { 29930 dropMatch = true; 29931 malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch); 29932 } 29933 break; 29934 } else if (isSubsetOf(altMatch2, altMatch)) { 29935 setMergeLocators(altMatch2, altMatch); 29936 break; 29937 } else if (staticCanMatchDefinition(altMatch, altMatch2)) { 29938 if (setMergeLocators(altMatch, altMatch2)) { 29939 dropMatch = true; 29940 malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch); 29941 } 29942 break; 29943 } 29944 } 29945 } 29946 if (!dropMatch) { 29947 malternateMatches.push(altMatch); 29948 } 29949 } 29950 } 29951 matches = currentMatches.concat(malternateMatches); 29952 testPos = pos; 29953 insertStop = matches.length > 0; 29954 match = malternateMatches.length > 0; 29955 ndxInitializer = ndxInitializerClone.slice(); 29956 } else match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse); 29957 if (match) return true; 29958 } else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[$.inArray(match, maskToken.matches) - 1]) { 29959 var qt = match; 29960 for (var qndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && testPos <= pos; qndx++) { 29961 var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1]; 29962 match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), tokenGroup); 29963 if (match) { 29964 latestMatch = matches[matches.length - 1].match; 29965 latestMatch.optionalQuantifier = qndx >= qt.quantifier.min; 29966 latestMatch.jit = (qndx || 1) * tokenGroup.matches.indexOf(latestMatch) >= qt.quantifier.jit; 29967 if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) { 29968 insertStop = true; 29969 testPos = pos; 29970 break; 29971 } 29972 if (latestMatch.jit) { 29973 getMaskSet().jitOffset[pos] = tokenGroup.matches.indexOf(latestMatch); 29974 } 29975 return true; 29976 } 29977 } 29978 } else { 29979 match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse); 29980 if (match) return true; 29981 } 29982 } else { 29983 testPos++; 29984 } 29985 } 29986 for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) { 29987 if (maskToken.matches[tndx].isQuantifier !== true) { 29988 var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse); 29989 if (match && testPos === pos) { 29990 return match; 29991 } else if (testPos > pos) { 29992 break; 29993 } 29994 } 29995 } 29996 } 29997 function mergeLocators(pos, tests) { 29998 var locator = []; 29999 if (!$.isArray(tests)) tests = [ tests ]; 30000 if (tests.length > 0) { 30001 if (tests[0].alternation === undefined) { 30002 locator = determineTestTemplate(pos, tests.slice()).locator.slice(); 30003 if (locator.length === 0) locator = tests[0].locator.slice(); 30004 } else { 30005 $.each(tests, function(ndx, tst) { 30006 if (tst.def !== "") { 30007 if (locator.length === 0) locator = t
30007st.locator.slice(); else { 30008 for (var i = 0; i < locator.length; i++) { 30009 if (tst.locator[i] && locator[i].toString().indexOf(tst.locator[i]) === -1) { 30010 locator[i] += "," + tst.locator[i]; 30011 } 30012 } 30013 } 30014 } 30015 }); 30016 } 30017 } 30018 return locator; 30019 } 30020 if (pos > -1) { 30021 if (ndxIntlzr === undefined) { 30022 var previousPos = pos - 1, test; 30023 while ((test = getMaskSet().validPositions[previousPos] || getMaskSet().tests[previousPos]) === undefined && previousPos > -1) { 30024 previousPos--; 30025 } 30026 if (test !== undefined && previousPos > -1) { 30027 ndxInitializer = mergeLocators(previousPos, test); 30028 cacheDependency = ndxInitializer.join(""); 30029 testPos = previousPos; 30030 } 30031 } 30032 if (getMaskSet().tests[pos] && getMaskSet().tests[pos][0].cd === cacheDependency) { 30033 return getMaskSet().tests[pos]; 30034 } 30035 for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) { 30036 var match = resolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]); 30037 if (match && testPos === pos || testPos > pos) { 30038 break; 30039 } 30040 } 30041 } 30042 if (matches.length === 0 || insertStop) { 30043 matches.push({ 30044 match: { 30045 fn: null, 30046 optionality: false, 30047 casing: null, 30048 def: "", 30049 placeholder: "" 30050 }, 30051 locator: [], 30052 mloc: {}, 30053 cd: cacheDependency 30054 }); 30055 } 30056 if (ndxIntlzr !== undefined && getMaskSet().tests[pos]) { 30057 return $.extend(true, [], matches); 30058 } 30059 getMaskSet().tests[pos] = $.extend(true, [], matches); 30060 return getMaskSet().tests[pos]; 30061 } 30062 function getBufferTemplate() { 30063 if (getMaskSet()._buffer === undefined) { 30064 getMaskSet()._buffer = getMaskTemplate(false, 1); 30065 if (getMaskSet().buffer === undefined) getMaskSet().buffer = getMaskSet()._buffer.slice(); 30066 } 30067 return getMaskSet()._buffer; 30068 } 30069 function getBuffer(noCache) { 30070 if (getMaskSet().buffer === undefined || noCache === true) { 30071 getMaskSet().buffer = getMaskTemplate(true, getLastValidPosition(), true); 30072 if (getMaskSet()._buffer === undefined) getMaskSet()._buffer = getMaskSet().buffer.slice(); 30073 } 30074 return getMaskSet().buffer; 30075 } 30076 function refreshFromBuffer(start, end, buffer) { 30077 var i, p; 30078 if (start === true) { 30079 resetMaskSet(); 30080 start = 0; 30081 end = buffer.length; 30082 } else { 30083 for (i = start; i < end; i++) { 30084 delete getMaskSet().validPositions[i]; 30085 } 30086 } 30087 p = start; 30088 for (i = start; i < end; i++) { 30089 resetMaskSet(true); 30090 if (buffer[i] !== opts.skipOptionalPartCharacter) { 30091 var valResult = isValid(p, buffer[i], true, true); 30092 if (valResult !== false) { 30093 resetMaskSet(true); 30094 p = valResult.caret !== undefined ? valResult.caret : valResult.pos + 1; 30095 } 30096 } 30097 } 30098 } 30099 function casing(elem, test, pos) { 30100 switch (opts.casing || test.casing) { 30101 case "upper": 30102 elem = elem.toUpperCase(); 30103 break; 30104 30105 case "lower": 30106 elem = elem.toLowerCase(); 30107 break; 30108 30109 case "title": 30110 var posBefore = getMaskSet().validPositions[pos - 1]; 30111 if (pos === 0 || posBefore && posBefore.input === String.fromCharCode(Inputmask.keyCode.SPACE)) { 30112 elem = elem.toUpperCase(); 30113 } else { 30114 elem = elem.toLowerCase(); 30115 } 30116 break; 30117 30118 default: 30119 if ($.isFunction(opts.casing)) { 30120 var args = Array.prototype.slice.call(arguments); 30121 args.push(getMaskSet().validPositions); 30122 elem = opts.casing.apply(this, args); 30123 } 30124 } 30125 return elem; 30126 } 30127 function checkAlternationMatch(altArr1, altArr2, na) { 30128 var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = false, naArr = na !== undefined ? na.split(",") : [], naNdx; 30129 for (var i = 0; i < naArr.length; i++) { 30130 if ((naNdx = altArr1.indexOf(naArr[i])) !== -1) { 30131 altArr1.splice(naNdx, 1); 30132 } 30133 } 30134 for (var alndx = 0; alndx < altArr1.length; alndx++) { 30135 if ($.inArray(altArr1[alndx], altArrC) !== -1) { 30136 isMatch = true; 30137 break; 30138 } 30139 } 30140 return isMatch; 30141 } 30142 function alternate(pos, c, strict, fromSetValid, rAltPos) {
30143 var validPsClone = $.extend(true, {}, getMaskSet().validPositions), lastAlt, alternation, isValidRslt = false, altPos, prevAltPos, i, validPos, decisionPos, lAltPos = rAltPos !== undefined ? rAltPos : getLastValidPosition(); 30144 if (lAltPos === -1 && rAltPos === undefined) { 30145 lastAlt = 0; 30146 prevAltPos = getTest(lastAlt); 30147 alternation = prevAltPos.alternation; 30148 } else { 30149 for (;lAltPos >= 0; lAltPos--) { 30150 altPos = getMaskSet().validPositions[lAltPos]; 30151 if (altPos && altPos.alternation !== undefined) { 30152 if (prevAltPos && prevAltPos.locator[altPos.alternation] !== altPos.locator[altPos.alternation]) { 30153 break; 30154 } 30155 lastAlt = lAltPos; 30156 alternation = getMaskSet().validPositions[lastAlt].alternation; 30157 prevAltPos = altPos; 30158 } 30159 } 30160 } 30161 if (alternation !== undefined) { 30162 decisionPos = parseInt(lastAlt); 30163 getMaskSet().excludes[decisionPos] = getMaskSet().excludes[decisionPos] || []; 30164 if (pos !== true) { 30165 getMaskSet().excludes[decisionPos].push(getDecisionTaker(prevAltPos)); 30166 } 30167 var validInputsClone = [], staticInputsBeforePos = 0; 30168 for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) { 30169 validPos = getMaskSet().validPositions[i]; 30170 if (validPos && validPos.generatedInput !== true) { 30171 validInputsClone.push(validPos.input); 30172 } else if (i < pos) staticInputsBeforePos++; 30173 delete getMaskSet().validPositions[i]; 30174 } 30175 while (getMaskSet().excludes[decisionPos] && getMaskSet().excludes[decisionPos].length < 10) { 30176 var posOffset = staticInputsBeforePos * -1, validInputs = validInputsClone.slice(); 30177 getMaskSet().tests[decisionPos] = undefined; 30178 resetMaskSet(true); 30179 isValidRslt = true; 30180 while (validInputs.length > 0) { 30181 var input = validInputs.shift(); 30182 if (!(isValidRslt = isValid(getLastValidPosition(undefined, true) + 1, input, false, fromSetValid, true))) { 30183 break; 30184 } 30185 } 30186 if (isValidRslt && c !== undefined) { 30187 var targetLvp = getLastValidPosition(pos) + 1; 30188 for (i = decisionPos; i < getLastValidPosition() + 1; i++) { 30189 validPos = getMaskSet().validPositions[i]; 30190 if ((validPos === undefined || validPos.match.fn == null) && i < pos + posOffset) { 30191 posOffset++; 30192 } 30193 } 30194 pos = pos + posOffset; 30195 isValidRslt = isValid(pos > targetLvp ? targetLvp : pos, c, strict, fromSetValid, true); 30196 } 30197 if (!isValidRslt) { 30198 resetMaskSet(); 30199 prevAltPos = getTest(decisionPos); 30200 getMaskSet().validPositions = $.extend(true, {}, validPsClone); 30201 if (getMaskSet().excludes[decisionPos]) { 30202 var decisionTaker = getDecisionTaker(prevAltPos); 30203 if (getMaskSet().excludes[decisionPos].indexOf(decisionTaker) !== -1) { 30204 isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1); 30205 break; 30206 } 30207 getMaskSet().excludes[decisionPos].push(decisionTaker); 30208 for (i = decisionPos; i < getLastValidPosition(undefined, true) + 1; i++) { 30209 delete getMaskSet().validPositions[i]; 30210 } 30211 } else { 30212 isValidRslt = alternate(pos, c, strict, fromSetValid, decisionPos - 1); 30213 break; 30214 } 30215 } else break; 30216 } 30217 } 30218 getMaskSet().excludes[decisionPos] = undefined; 30219 return isValidRslt; 30220 } 30221 function isValid(pos, c, strict, fromSetValid, fromAlternate, validateOnly) { 30222 function isSelection(posObj) { 30223 return isRTL ? posObj.begin - posObj.end > 1 || posObj.begin - posObj.end === 1 : posObj.end - posObj.begin > 1 || posObj.end - posObj.begin === 1; 30224 }
30225 strict = strict === true; 30226 var maskPos = pos; 30227 if (pos.begin !== undefined) { 30228 maskPos = isRTL ? pos.end : pos.begin; 30229 } 30230 function _isValid(position, c, strict) { 30231 var rslt = false; 30232 $.each(getTests(position), function(ndx, tst) { 30233 var test = tst.match; 30234 getBuffer(true); 30235 rslt = test.fn != null ? test.fn.test(c, getMaskSet(), position, strict, opts, isSelection(pos)) : (c === test.def || c === opts.skipOptionalPartCharacter) && test.def !== "" ? { 30236 c: getPlaceholder(position, test, true) || test.def, 30237 pos: position 30238 } : false; 30239 if (rslt !== false) { 30240 var elem = rslt.c !== undefined ? rslt.c : c, validatedPos = position; 30241 elem = elem === opts.skipOptionalPartCharacter && test.fn === null ? getPlaceholder(position, test, true) || test.def : elem; 30242 if (rslt.remove !== undefined) { 30243 if (!$.isArray(rslt.remove)) rslt.remove = [ rslt.remove ]; 30244 $.each(rslt.remove.sort(function(a, b) { 30245 return b - a; 30246 }), function(ndx, lmnt) { 30247 revalidateMask({ 30248 begin: lmnt, 30249 end: lmnt + 1 30250 }); 30251 }); 30252 } 30253 if (rslt.insert !== undefined) { 30254 if (!$.isArray(rslt.insert)) rslt.insert = [ rslt.insert ]; 30255 $.each(rslt.insert.sort(function(a, b) { 30256 return a - b; 30257 }), function(ndx, lmnt) { 30258 isValid(lmnt.pos, lmnt.c, true, fromSetValid); 30259 }); 30260 } 30261 if (rslt !== true && rslt.pos !== undefined && rslt.pos !== position) { 30262 validatedPos = rslt.pos; 30263 } 30264 if (rslt !== true && rslt.pos === undefined && rslt.c === undefined) { 30265 return false; 30266 } 30267 if (!revalidateMask(pos, $.extend({}, tst, { 30268 input: casing(elem, test, validatedPos) 30269 }), fromSetValid, validatedPos)) { 30270 rslt = false; 30271 } 30272 return false; 30273 } 30274 }); 30275 return rslt; 30276 } 30277 var result = true, positionsClone = $.extend(true, {}, getMaskSet().validPositions); 30278 if ($.isFunction(opts.preValidation) && !strict && fromSetValid !== true && validateOnly !== true) { 30279 result = opts.preValidation(getBuffer(), maskPos, c, isSelection(pos), opts, getMaskSet()); 30280 } 30281 if (result === true) { 30282 trackbackPositions(undefined, maskPos, true); 30283 if (maxLength === undefined || maskPos < maxLength) { 30284 result = _isValid(maskPos, c, strict); 30285 if ((!strict || fromSetValid === true) && result === false && validateOnly !== true) { 30286 var currentPosValid = getMaskSet().validPositions[maskPos]; 30287 if (currentPosValid && currentPosValid.match.fn === null && (currentPosValid.match.def === c || c === opts.skipOptionalPartCharacter)) { 30288 result = { 30289 caret: seekNext(maskPos) 30290 }; 30291 } else { 30292 if ((opts.insertMode || getMaskSet().validPositions[seekNext(maskPos)] === undefined) && (!isMask(maskPos, true) || getMaskSet().jitOffset[maskPos])) { 30293 if (getMaskSet().jitOffset[maskPos] && getMaskSet().validPositions[seekNext(maskPos)] === undefined) { 30294 result = isValid(maskPos + getMaskSet().jitOffset[maskPos], c, strict); 30295 if (result !== false) result.caret = maskPos; 30296 } else for (var nPos = maskPos + 1, snPos = seekNext(maskPos); nPos <= snPos; nPos++) { 30297 result = _isValid(nPos, c, strict); 30298 if (result !== false) { 30299 result = trackbackPositions(maskPos, result.pos !== undefined ? result.pos : nPos) || result; 30300 maskPos = nPos; 30301 break; 30302 } 30303 } 30304 } 30305 } 30306 } 30307 } 30308 if (result === false && opts.keepStatic !== false && (opts.regex == null || isComplete(getBuffer())) && !strict && fromAlternate !== true) { 30309 result = alternate(maskPos, c, strict, fromSetValid); 30310 } 30311 if (result === true) { 30312 result = { 30313 pos: maskPos 30314 }; 30315 } 30316 } 30317 if ($.isFunction(opts.postValidation) && result !== false && !strict && fromSetValid !== true && validateOnly !== true) { 30318 var postResult = opts.postValidation(getBuffer(true), pos.begin !== undefined ? isRTL ? pos.end : pos.begin : pos, result, opts); 30319 if (postResult !== undefined) { 30320 if (postResult.refreshFromBuffer && postResult.buffer) { 30321 var refresh = postResult.refreshFromBuffer; 30322 refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, postResult.buffer); 30323 } 30324 result = postResult === true ? result : postResult; 30325 } 30326 } 30327 if (result && result.pos === undefined) { 30328 result.pos = maskPos; 30329 } 30330 if (result === false || validateOnly === true) { 30331 resetMaskSet(true); 30332 getMaskSet().validPositions = $.extend(true, {}, positionsClone); 30333 } 30334 return result; 30335 } 30336 function trackbackPositions(originalPos, newPos, fillOnly) { 30337 var result; 30338 if (originalPos === undefined) { 30339 for (originalPos = newPos - 1; originalPos > 0; originalPos--) { 30340 if (getMaskSet().validPositions[originalPos]) break; 30341 } 30342 } 30343 for (var ps = originalPos; ps < newPos; ps++) { 30344 if (getMaskSet().validPositions[ps] === undefined && !isMask(ps, true)) { 30345 var vp = ps == 0 ? getTest(ps) : getMaskSet().validPositions[ps - 1]; 30346 if (vp) { 30347 var tests = getTests(ps).slice(); 30348 if (tests[tests.length - 1].match.def === "") tests.pop(); 30349 var bestMatch = determineTestTemplate(ps, tests); 30350 bestMatch = $.extend({}, bestMatch, { 30351 input: getPlaceholder(ps, bestMatch.match, true) || bestMatch.match.def 30352 }); 30353 bestMatch.generatedInput = true; 30354 revalidateMask(ps, bestMatch, true); 30355 if (fillOnly !== true) { 30356 var cvpInput = getMaskSet().validPositions[newPos].input; 30357 getMaskSet().validPositions[newPos] = undefined; 30358 result = isValid(newPos, cvpInput, true, true); 30359 } 30360 } 30361 } 30362 } 30363 return result; 30364 } 30365 function revalidateMask(pos, validTest, fromSetValid, validatedPos) { 30366 function IsEnclosedStatic(pos, valids, selection) { 30367 var posMatch = valids[pos]; 30368 if (posMatch !== undefined && (posMatch.match.fn === null && posMatch.match.optionality !== true || posMatch.input === opts.radixPoint)) { 30369 var prevMatch = selection.begin <= pos - 1 ? valids[pos - 1] && valids[pos - 1].match.fn === null && valids[pos - 1] : valids[pos - 1], nextMatch = selection.end > pos + 1 ? valids[pos + 1] && valids[pos + 1].match.fn === null && valids[pos + 1] : valids[pos + 1]; 30370 return prevMatch && nextMatch; 30371 } 30372 return false;
30373 } 30374 var begin = pos.begin !== undefined ? pos.begin : pos, end = pos.end !== undefined ? pos.end : pos; 30375 if (pos.begin > pos.end) { 30376 begin = pos.end; 30377 end = pos.begin; 30378 } 30379 validatedPos = validatedPos !== undefined ? validatedPos : begin; 30380 if (begin !== end || opts.insertMode && getMaskSet().validPositions[validatedPos] !== undefined && fromSetValid === undefined) { 30381 var positionsClone = $.extend(true, {}, getMaskSet().validPositions), lvp = getLastValidPosition(undefined, true), i; 30382 getMaskSet().p = begin; 30383 for (i = lvp; i >= begin; i--) { 30384 if (getMaskSet().validPositions[i] && getMaskSet().validPositions[i].match.nativeDef === "+") { 30385 opts.isNegative = false; 30386 } 30387 delete getMaskSet().validPositions[i]; 30388 } 30389 var valid = true, j = validatedPos, vps = getMaskSet().validPositions, needsValidation = false, posMatch = j, i = j; 30390 if (validTest) { 30391 getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest); 30392 posMatch++; 30393 j++; 30394 if (begin < end) i++; 30395 } 30396 for (;i <= lvp; i++) { 30397 var t = positionsClone[i]; 30398 if (t !== undefined && (i >= end || i >= begin && t.generatedInput !== true && IsEnclosedStatic(i, positionsClone, { 30399 begin: begin, 30400 end: end 30401 }))) { 30402 while (getTest(posMatch).match.def !== "") { 30403 if (needsValidation === false && positionsClone[posMatch] && positionsClone[posMatch].match.nativeDef === t.match.nativeDef) { 30404 getMaskSet().validPositions[posMatch] = $.extend(true, {}, positionsClone[posMatch]); 30405 getMaskSet().validPositions[posMatch].input = t.input; 30406 trackbackPositions(undefined, posMatch, true); 30407 j = posMatch + 1; 30408 valid = true; 30409 } else if (opts.shiftPositions && positionCanMatchDefinition(posMatch, t.match.def)) { 30410 var result = isValid(posMatch, t.input, true, true); 30411 valid = result !== false; 30412 j = result.caret || result.insert ? getLastValidPosition() : posMatch + 1; 30413 needsValidation = true; 30414 } else { 30415 valid = t.generatedInput === true || t.input === opts.radixPoint && opts.numericInput === true; 30416 } 30417 if (valid) break; 30418 if (!valid && posMatch > end && isMask(posMatch, true) && (t.match.fn !== null || posMatch > getMaskSet().maskLength)) { 30419 break; 30420 } 30421 posMatch++; 30422 } 30423 if (getTest(posMatch).match.def == "") valid = false; 30424 posMatch = j; 30425 } 30426 if (!valid) break; 30427 } 30428 if (!valid) { 30429 getMaskSet().validPositions = $.extend(true, {}, positionsClone); 30430 resetMaskSet(true); 30431 return false; 30432 } 30433 } else if (validTest) { 30434 getMaskSet().validPositions[validatedPos] = $.extend(true, {}, validTest); 30435 } 30436 resetMaskSet(true); 30437 return true; 30438 } 30439 function isMask(pos, strict) { 30440 var test = getTestTemplate(pos).match; 30441 if (test.def === "") test = getTest(pos).match; 30442 if (test.fn != null) { 30443 return test.fn; 30444 } 30445 if (strict !== true && pos > -1) { 30446 var tests = getTests(pos); 30447 return tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0); 30448 } 30449 return false;
30450 } 30451 function seekNext(pos, newBlock) { 30452 var position = pos + 1; 30453 while (getTest(position).match.def !== "" && (newBlock === true && (getTest(position).match.newBlockMarker !== true || !isMask(position)) || newBlock !== true && !isMask(position))) { 30454 position++; 30455 } 30456 return position; 30457 } 30458 function seekPrevious(pos, newBlock) { 30459 var position = pos, tests; 30460 if (position <= 0) return 0; 30461 while (--position > 0 && (newBlock === true && getTest(position).match.newBlockMarker !== true || newBlock !== true && !isMask(position) && (tests = getTests(position), 30462 tests.length < 2 || tests.length === 2 && tests[1].match.def === ""))) {} 30463 return position; 30464 } 30465 function writeBuffer(input, buffer, caretPos, event, triggerEvents) { 30466 if (event && $.isFunction(opts.onBeforeWrite)) { 30467 var result = opts.onBeforeWrite.call(inputmask, event, buffer, caretPos, opts); 30468 if (result) { 30469 if (result.refreshFromBuffer) { 30470 var refresh = result.refreshFromBuffer; 30471 refreshFromBuffer(refresh === true ? refresh : refresh.start, refresh.end, result.buffer || buffer); 30472 buffer = getBuffer(true); 30473 } 30474 if (caretPos !== undefined) caretPos = result.caret !== undefined ? result.caret : caretPos; 30475 } 30476 } 30477 if (input !== undefined) { 30478 input.inputmask._valueSet(buffer.join("")); 30479 if (caretPos !== undefined && (event === undefined || event.type !== "blur")) { 30480 caret(input, caretPos); 30481 } else renderColorMask(input, caretPos, buffer.length === 0); 30482 if (triggerEvents === true) { 30483 var $input = $(input), nptVal = input.inputmask._valueGet(); 30484 skipInputEvent = true; 30485 $input.trigger("input"); 30486 setTimeout(function() { 30487 if (nptVal === getBufferTemplate().join("")) { 30488 $input.trigger("cleared"); 30489 } else if (isComplete(buffer) === true) { 30490 $input.trigger("complete"); 30491 } 30492 }, 0); 30493 } 30494 } 30495 } 30496 function getPlaceholder(pos, test, returnPL) { 30497 test = test || getTest(pos).match; 30498 if (test.placeholder !== undefined || returnPL === true) { 30499 return $.isFunction(test.placeholder) ? test.placeholder(opts) : test.placeholder; 30500 } else if (test.fn === null) { 30501 if (pos > -1 && getMaskSet().validPositions[pos] === undefined) { 30502 var tests = getTests(pos), staticAlternations = [], prevTest; 30503 if (tests.length > 1 + (tests[tests.length - 1].match.def === "" ? 1 : 0)) { 30504 for (var i = 0; i < tests.length; i++) { 30505 if (tests[i].match.optionality !== true && tests[i].match.optionalQuantifier !== true && (tests[i].match.fn === null || prevTest === undefined || tests[i].match.fn.test(prevTest.match.def, getMaskSet(), pos, true, opts) !== false)) { 30506 staticAlternations.push(tests[i]); 30507 if (tests[i].match.fn === null) prevTest = tests[i]; 30508 if (staticAlternations.length > 1) { 30509 if (/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)) { 30510 return opts.placeholder.charAt(pos % opts.placeholder.length); 30511 } 30512 } 30513 } 30514 } 30515 } 30516 } 30517 return test.def; 30518 } 30519 return opts.placeholder.charAt(pos % opts.placeholder.length); 30520 } 30521 function HandleNativePlaceholder(npt, value) { 30522 if (ie) { 30523 if (npt.inputmask._valueGet() !== value && (npt.placeholder !== value || npt.placeholder === "")) { 30524 var buffer = getBuffer().slice(), nptValue = npt.inputmask._valueGet(); 30525 if (nptValue !== value) { 30526 var lvp = getLastValidPosition(); 30527 if (lvp === -1 && nptValue === getBufferTemplate().join("")) { 30528 buffer = []; 30529 } else if (lvp !== -1) { 30530 clearOptionalTail(buffer); 30531 } 30532 writeBuffer(npt, buffer); 30533 } 30534 } 30535 } else if (npt.placeholder !== value) { 30536 npt.placeholder = value; 30537 if (npt.placeholder === "") npt.removeAttribute("placeholder"); 30538 } 30539 } 30540 var EventRuler = { 30541 on: function on(input, eventName, eventHandler) { 30542 var ev = function ev(e) { 30543 var that = this; 30544 if (that.inputmask === undefined && this.nodeName !== "FORM") { 30545 var imOpts = $.data(that, "_inputmask_opts"); 30546 if (imOpts) new Inputmask(imOpts).mask(that); else EventRuler.off(that); 30547 } else if (e.type !== "setvalue" && this.nodeName !== "FORM" && (that.disabled || that.readOnly && !(e.type === "keydown" && e.ctrlKey && e.keyCode === 67 || opts.tabThrough === false && e.keyCode === Inputmask.keyCode.TAB))) { 30548 e.preventDefault(); 30549 } else { 30550 switch (e.type) { 30551 case "input": 30552 if (skipInputEvent === true) { 30553 skipInputEvent = false;
30554 return e.preventDefault(); 30555 } 30556 if (mobile) { 30557 var args = arguments; 30558 setTimeout(function() { 30559 eventHandler.apply(that, args); 30560 caret(that, that.inputmask.caretPos, undefined, true); 30561 }, 0); 30562 return false; 30563 } 30564 break; 30565 30566 case "keydown": 30567 skipKeyPressEvent = false; 30568 skipInputEvent = false; 30569 break; 30570 30571 case "keypress": 30572 if (skipKeyPressEvent === true) { 30573 return e.preventDefault(); 30574 } 30575 skipKeyPressEvent = true; 30576 break; 30577 30578 case "click": 30579 if (iemobile || iphone) { 30580 var args = arguments; 30581 setTimeout(function() { 30582 eventHandler.apply(that, args); 30583 }, 0); 30584 return false; 30585 } 30586 break; 30587 } 30588 var returnVal = eventHandler.apply(that, arguments); 30589 if (returnVal === false) { 30590 e.preventDefault(); 30591 e.stopPropagation(); 30592 } 30593 return returnVal; 30594 } 30595 }; 30596 input.inputmask.events[eventName] = input.inputmask.events[eventName] || []; 30597 input.inputmask.events[eventName].push(ev); 30598 if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) { 30599 if (input.form !== null) $(input.form).on(eventName, ev); 30600 } else { 30601 $(input).on(eventName, ev); 30602 } 30603 }, 30604 off: function off(input, event) { 30605 if (input.inputmask && input.inputmask.events) { 30606 var events; 30607 if (event) { 30608 events = []; 30609 events[event] = input.inputmask.events[event]; 30610 } else { 30611 events = input.inputmask.events; 30612 } 30613 $.each(events, function(eventName, evArr) { 30614 while (evArr.length > 0) { 30615 var ev = evArr.pop(); 30616 if ($.inArray(eventName, [ "submit", "reset" ]) !== -1) { 30617 if (input.form !== null) $(input.form).off(eventName, ev); 30618 } else { 30619 $(input).off(eventName, ev); 30620 } 30621 } 30622 delete input.inputmask.events[eventName]; 30623 }); 30624 } 30625 } 30626 }; 30627 var EventHandlers = { 30628 keydownEvent: function keydownEvent(e) { 30629 var input = this, $input = $(input), k = e.keyCode, pos = caret(input); 30630 if (k === Inputmask.keyCode.BACKSPACE || k === Inputmask.keyCode.DELETE || iphone && k === Inputmask.keyCode.BACKSPACE_SAFARI || e.ctrlKey && k === Inputmask.keyCode.X && !isInputEventSupported("cut")) { 30631 e.preventDefault(); 30632 handleRemove(input, k, pos); 30633 writeBuffer(input, getBuffer(true), getMaskSet().p, e, input.inputmask._valueGet() !== getBuffer().join("")); 30634 } else if (k === Inputmask.keyCode.END || k === Inputmask.keyCode.PAGE_DOWN) { 30635 e.preventDefault(); 30636 var caretPos = seekNext(getLastValidPosition()); 30637 caret(input, e.shiftKey ? pos.begin : caretPos, caretPos, true); 30638 } else if (k === Inputmask.keyCode.HOME && !e.shiftKey || k === Inputmask.keyCode.PAGE_UP) { 30639 e.preventDefault(); 30640 caret(input, 0, e.shiftKey ? pos.begin : 0, true); 30641 } else if ((opts.undoOnEscape && k === Inputmask.keyCode.ESCAPE || k === 90 && e.ctrlKey) && e.altKey !== true) { 30642 checkVal(input, true, false, undoValue.split("")); 30643 $input.trigger("click"); 30644 } else if (k === Inputmask.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) { 30645 opts.insertMode = !opts.insertMode; 30646 input.setAttribute("im-insert", opts.insertMode); 30647 } else if (opts.tabThrough === true && k === Inputmask.keyCode.TAB) { 30648 if (e.shiftKey === true) { 30649 if (getTest(pos.begin).match.fn === null) { 30650 pos.begin = seekNext(pos.begin); 30651 } 30652 pos.end = seekPrevious(pos.begin, true); 30653 pos.begin = seekPrevious(pos.end, true); 30654 } else { 30655 pos.begin = seekNext(pos.begin, true); 30656 pos.end = seekNext(pos.begin, true); 30657 if (pos.end < getMaskSet().maskLength) pos.end--; 30658 } 30659 if (pos.begin < getMaskSet().maskLength) { 30660 e.preventDefault(); 30661 caret(input, pos.begin, pos.end); 30662 } 30663 } 30664 opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts); 30665 ignorable = $.inArray(k, opts.ignorables) !== -1; 30666 }, 30667 keypressEvent: function keypressEvent(e, checkval, writeOut, strict, ndx) { 30668 var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode; 30669 if (checkval !== true && !(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) { 30670 if (k === Inputmask.keyCode.ENTER && undoValue !== getBuffer().join("")) { 30671 undoValue = getBuffer().join(""); 30672 setTimeout(function() { 30673 $input.trigger("change"); 30674 }, 0); 30675 } 30676 return true; 30677 } else { 30678 if (k) { 30679 if (k === 46 && e.shiftKey === false && opts.radixPoint !== "") k = opts.radixPoint.charCodeAt(0); 30680 var pos = checkval ? { 30681 begin: ndx, 30682 end: ndx 30683 } : caret(input), forwardPosition, c = String.fromCharCode(k), offset = 0; 30684 if (opts._radixDance && opts.numericInput) { 30685 var caretPos = getBuffer().indexOf(opts.radixPoint.charAt(0)) + 1; 30686 if (pos.begin <= caretPos) { 30687 if (k === opts.radixPoint.charCodeAt(0)) offset = 1; 30688 pos.begin -= 1; 30689 pos.end -= 1; 30690 } 30691 } 30692 getMaskSet().writeOutBuffer = true; 30693 var valResult = isValid(pos, c, strict); 30694 if (valResult !== false) { 30695 resetMaskSet(true); 30696 forwardPosition = valResult.caret !== undefined ? valResult.caret : seekNext(valResult.pos.begin ? valResult.pos.begin : valResult.pos); 30697 getMaskSet().p = forwardPosition; 30698 } 30699 forwardPosition = (opts.numericInput && valResult.caret === undefined ? seekPrevious(forwardPosition) : forwardPosition) + offset; 30700 if (writeOut !== false) { 30701 setTimeout(function() { 30702 opts.onKeyValidation.call(input, k, valResult, opts); 30703 }, 0); 30704 if (getMaskSet().writeOutBuffer && valResult !== false) { 30705 var buffer = getBuffer(); 30706 writeBuffer(input, buffer, forwardPosition, e, checkval !== true); 30707 } 30708 } 30709 e.preventDefault(); 30710 if (checkval) { 30711 if (valResult !== false) valResult.forwardPosition = forwardPosition; 30712 return valResult; 30713 } 30714 } 30715 } 30716 }, 30717 pasteEvent: function pasteEvent(e) { 30718 var input = this, ev = e.originalEvent || e, $input = $(input), inputValue = input.inputmask._valueGet(true), caretPos = caret(input), tempValue; 30719 if (isRTL) { 30720 tempValue = caretPos.end; 30721 caretPos.end = caretPos.begin; 30722 caretPos.begin = tempValue; 30723 } 30724 var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length); 30725 if (valueBeforeCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(0, caretPos.begin).join("")) valueBeforeCaret = ""; 30726 if (valueAfterCaret === (isRTL ? getBufferTemplate().reverse() : getBufferTemplate()).slice(caretPos.end).join("")) valueAfterCaret = ""; 30727 if (window.clipboardData && window.clipboardData.getData) { 30728 inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret; 30729 } else if (ev.clipboardData && ev.clipboardData.getData) { 30730 inputValue = valueBeforeCaret + ev.clipboardData.getData("text/plain") + valueAfterCaret; 30731 } else return true; 30732 var pasteValue = inputValue; 30733 if ($.isFunction(opts.onBeforePaste)) { 30734 pasteValue = opts.onBeforePaste.call(inputmask, inputValue, opts); 30735 if (pasteValue === false) { 30736 return e.preventDefault(); 30737 } 30738 if (!pasteValue) { 30739 pasteValue = inputValue; 30740 } 30741 } 30742 checkVal(input, false, false, pasteValue.toString().split("")); 30743 writeBuffer(input, getBuffer(), seekNext(getLastValidPosition()), e, undoValue !== getBuffer().join("")); 30744 return e.preventDefault(); 30745 }, 30746 inputFallBackEvent: function inputFallBackEvent(e) { 30747 function radixPointHandler(input, inputValue, caretPos) { 30748 if (inputValue.charAt(caretPos.begin - 1) === "." && opts.radixPoint !== "") { 30749 inputValue = inputValue.split(""); 30750 inputValue[caretPos.begin - 1] = opts.radixPoint.charAt(0); 30751 inputValue = inputValue.join(""); 30752 } 30753 return inputValue; 30754 } 30755 function ieMobileHandler(input, inputValue, caretPos) { 30756 if (iemobile) { 30757 var inputChar = inputValue.replace(getBuffer().join(""), ""); 30758 if (inputChar.length === 1) { 30759 var iv = inputValue.split(""); 30760 iv.splice(caretPos.begin, 0, inputChar); 30761 inputValue = iv.join(""); 30762 } 30763 } 30764 return inputValue; 30765 } 30766 var input = this, inputValue = input.inputmask._valueGet(); 30767 if (getBuffer().join("") !== inputValue) { 30768 var caretPos = caret(input); 30769 inputValue = radixPointHandler(input, inputValue, caretPos); 30770 inputValue = ieMobileHandler(input, inputValue, caretPos); 30771 if (getBuffer().join("") !== inputValue) { 30772 var buffer = getBuffer().join(""), offset = !opts.numericInput && inputValue.length > buffer.length ? -1 : 0, frontPart = inputValue.substr(0, caretPos.begin), backPart = inputValue.substr(caretPos.begin), frontBufferPart = buffer.substr(0, caretPos.begin + offset), backBufferPart = buffer.substr(caretPos.begin + offset); 30773 var selection = caretPos, entries = "", isEntry = false;
30774 if (frontPart !== frontBufferPart) { 30775 var fpl = (isEntry = frontPart.length >= frontBufferPart.length) ? frontPart.length : frontBufferPart.length, i; 30776 for (i = 0; frontPart.charAt(i) === frontBufferPart.charAt(i) && i < fpl; i++) {} 30777 if (isEntry) { 30778 selection.begin = i - offset; 30779 entries += frontPart.slice(i, selection.end); 30780 } 30781 } 30782 if (backPart !== backBufferPart) { 30783 if (backPart.length > backBufferPart.length) { 30784 entries += backPart.slice(0, 1); 30785 } else { 30786 if (backPart.length < backBufferPart.length) { 30787 selection.end += backBufferPart.length - backPart.length; 30788 if (!isEntry && opts.radixPoint !== "" && backPart === "" && frontPart.charAt(selection.begin + offset - 1) === opts.radixPoint) { 30789 selection.begin--; 30790 entries = opts.radixPoint; 30791 } 30792 } 30793 } 30794 } 30795 writeBuffer(input, getBuffer(), { 30796 begin: selection.begin + offset, 30797 end: selection.end + offset 30798 }); 30799 if (entries.length > 0) { 30800 $.each(entries.split(""), function(ndx, entry) { 30801 var keypress = new $.Event("keypress"); 30802 keypress.which = entry.charCodeAt(0); 30803 ignorable = false; 30804 EventHandlers.keypressEvent.call(input, keypress); 30805 }); 30806 } else { 30807 if (selection.begin === selection.end - 1) { 30808 selection.begin = seekPrevious(selection.begin + 1); 30809 if (selection.begin === selection.end - 1) { 30810 caret(input, selection.begin); 30811 } else { 30812 caret(input, selection.begin, selection.end); 30813 } 30814 } 30815 var keydown = new $.Event("keydown"); 30816 keydown.keyCode = opts.numericInput ? Inputmask.keyCode.BACKSPACE : Inputmask.keyCode.DELETE; 30817 EventHandlers.keydownEvent.call(input, keydown); 30818 } 30819 e.preventDefault(); 30820 } 30821 } 30822 }, 30823 beforeInputEvent: function beforeInputEvent(e) { 30824 if (e.cancelable) { 30825 var input = this; 30826 switch (e.inputType) { 30827 case "insertText": 30828 $.each(e.data.split(""), function(ndx, entry) { 30829 var keypress = new $.Event("keypress"); 30830 keypress.which = entry.charCodeAt(0); 30831 ignorable = false; 30832 EventHandlers.keypressEvent.call(input, keypress); 30833 }); 30834 return e.preventDefault(); 30835 30836 case "deleteContentBackward": 30837 var keydown = new $.Event("keydown"); 30838 keydown.keyCode = Inputmask.keyCode.BACKSPACE; 30839 EventHandlers.keydownEvent.call(input, keydown); 30840 return e.preventDefault(); 30841 30842 case "deleteContentForward":
30843 var keydown = new $.Event("keydown"); 30844 keydown.keyCode = Inputmask.keyCode.DELETE; 30845 EventHandlers.keydownEvent.call(input, keydown); 30846 return e.preventDefault(); 30847 } 30848 } 30849 }, 30850 setValueEvent: function setValueEvent(e) { 30851 this.inputmask.refreshValue = false; 30852 var input = this, value = e && e.detail ? e.detail[0] : arguments[1], value = value || input.inputmask._valueGet(true); 30853 if ($.isFunction(opts.onBeforeMask)) value = opts.onBeforeMask.call(inputmask, value, opts) || value; 30854 value = value.toString().split(""); 30855 checkVal(input, true, false, value); 30856 undoValue = getBuffer().join(""); 30857 if ((opts.clearMaskOnLostFocus || opts.clearIncomplete) && input.inputmask._valueGet() === getBufferTemplate().join("")) { 30858 input.inputmask._valueSet(""); 30859 } 30860 }, 30861 focusEvent: function focusEvent(e) { 30862 var input = this, nptValue = input.inputmask._valueGet(); 30863 if (opts.showMaskOnFocus) { 30864 if (nptValue !== getBuffer().join("")) { 30865 writeBuffer(input, getBuffer(), seekNext(getLastValidPosition())); 30866 } else if (mouseEnter === false) { 30867 caret(input, seekNext(getLastValidPosition())); 30868 } 30869 } 30870 if (opts.positionCaretOnTab === true && mouseEnter === false) { 30871 EventHandlers.clickEvent.apply(input, [ e, true ]); 30872 } 30873 undoValue = getBuffer().join(""); 30874 }, 30875 mouseleaveEvent: function mouseleaveEvent(e) { 30876 var input = this; 30877 mouseEnter = false; 30878 if (opts.clearMaskOnLostFocus && document.activeElement !== input) { 30879 HandleNativePlaceholder(input, originalPlaceholder); 30880 } 30881 }, 30882 clickEvent: function clickEvent(e, tabbed) { 30883 function doRadixFocus(clickPos) { 30884 if (opts.radixPoint !== "") { 30885 var vps = getMaskSet().validPositions; 30886 if (vps[clickPos] === undefined || vps[clickPos].input === getPlaceholder(clickPos)) { 30887 if (clickPos < seekNext(-1)) return true; 30888 var radixPos = $.inArray(opts.radixPoint, getBuffer()); 30889 if (radixPos !== -1) { 30890 for (var vp in vps) { 30891 if (radixPos < vp && vps[vp].input !== getPlaceholder(vp)) { 30892 return false; 30893 } 30894 } 30895 return true; 30896 } 30897 } 30898 } 30899 return false; 30900 } 30901 var input = this; 30902 setTimeout(function() { 30903 if (document.activeElement === input) { 30904 var selectedCaret = caret(input); 30905 if (tabbed) { 30906 if (isRTL) { 30907 selectedCaret.end = selectedCaret.begin; 30908 } else { 30909 selectedCaret.begin = selectedCaret.end; 30910 } 30911 } 30912 if (selectedCaret.begin === selectedCaret.end) { 30913 switch (opts.positionCaretOnClick) { 30914 case "none": 30915 break; 30916 30917 case "select": 30918 caret(input, 0, getBuffer().length); 30919 break; 30920 30921 case "ignore": 30922 caret(input, seekNext(getLastValidPosition())); 30923 break; 30924 30925 case "radixFocus": 30926 if (doRadixFocus(selectedCaret.begin)) { 30927 var radixPos = getBuffer().join("").indexOf(opts.radixPoint); 30928 caret(input, opts.numericInput ? seekNext(radixPos) : radixPos); 30929 break; 30930 } 30931 30932 default: 30933 var clickPosition = selectedCaret.begin, lvclickPosition = getLastValidPosition(clickPosition, true), lastPosition = seekNext(lvclickPosition); 30934 if (clickPosition < lastPosition) { 30935 caret(input, !isMask(clickPosition, true) && !isMask(clickPosition - 1, true) ? seekNext(clickPosition) : clickPosition); 30936 } else { 30937 var lvp = getMaskSet().validPositions[lvclickPosition], tt = getTestTemplate(lastPosition, lvp ? lvp.match.locator : undefined, lvp), placeholder = getPlaceholder(lastPosition, tt.match); 30938 if (placeholder !== "" && getBuffer()[lastPosition] !== placeholder && tt.match.optionalQuantifier !== true && tt.match.newBlockMarker !== true || !isMask(lastPosition, opts.keepStatic) && tt.match.def === placeholder) { 30939 var newPos = seekNext(lastPosition); 30940 if (clickPosition >= newPos || clickPosition === lastPosition) { 30941 lastPosition = newPos; 30942 } 30943 } 30944 caret(input, lastPosition); 30945 } 30946 break; 30947 } 30948 } 30949 } 30950 }, 0); 30951 }, 30952 cutEvent: function cutEvent(e) { 30953 var input = this, $input = $(input), pos = caret(input), ev = e.originalEvent || e; 30954 var clipboardData = window.clipboardData || ev.clipboardData, clipData = isRTL ? getBuffer().slice(pos.end, pos.begin) : getBuffer().slice(pos.begin, pos.end); 30955 clipboardData.setData("text", isRTL ? clipData.reverse().join("") : clip
30955Data.join("")); 30956 if (document.execCommand) document.execCommand("copy"); 30957 handleRemove(input, Inputmask.keyCode.DELETE, pos); 30958 writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue !== getBuffer().join("")); 30959 }, 30960 blurEvent: function blurEvent(e) { 30961 var $input = $(this), input = this; 30962 if (input.inputmask) { 30963 HandleNativePlaceholder(input, originalPlaceholder); 30964 var nptValue = input.inputmask._valueGet(), buffer = getBuffer().slice(); 30965 if (nptValue !== "" || colorMask !== undefined) { 30966 if (opts.clearMaskOnLostFocus) { 30967 if (getLastValidPosition() === -1 && nptValue === getBufferTemplate().join("")) { 30968 buffer = []; 30969 } else { 30970 clearOptionalTail(buffer); 30971 } 30972 } 30973 if (isComplete(buffer) === false) { 30974 setTimeout(function() { 30975 $input.trigger("incomplete"); 30976 }, 0); 30977 if (opts.clearIncomplete) { 30978 resetMaskSet(); 30979 if (opts.clearMaskOnLostFocus) { 30980 buffer = []; 30981 } else { 30982 buffer = getBufferTemplate().slice(); 30983 } 30984 } 30985 } 30986 writeBuffer(input, buffer, undefined, e); 30987 } 30988 if (undoValue !== getBuffer().join("")) { 30989 undoValue = buffer.join(""); 30990 $input.trigger("change"); 30991 } 30992 } 30993 }, 30994 mouseenterEvent: function mouseenterEvent(e) { 30995 var input = this; 30996 mouseEnter = true; 30997 if (document.activeElement !== input && opts.showMaskOnHover) { 30998 HandleNativePlaceholder(input, (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("")); 30999 } 31000 }, 31001 submitEvent: function submitEvent(e) { 31002 if (undoValue !== getBuffer().join("")) { 31003 $el.trigger("change"); 31004 } 31005 if (opts.clearMaskOnLostFocus && getLastValidPosition() === -1 && el.inputmask._valueGet && el.inputmask._valueGet() === getBufferTemplate().join("")) { 31006 el.inputmask._valueSet(""); 31007 } 31008 if (opts.clearIncomplete && isComplete(getBuffer()) === false) { 31009 el.inputmask._valueSet(""); 31010 } 31011 if (opts.removeMaskOnSubmit) { 31012 el.inputmask._valueSet(el.inputmask.unmaskedvalue(), true); 31013 setTimeout(function() { 31014 writeBuffer(el, getBuffer()); 31015 }, 0); 31016 } 31017 }, 31018 resetEvent: function resetEvent(e) { 31019 el.inputmask.refreshValue = true; 31020 setTimeout(function() { 31021 $el.trigger("setvalue"); 31022 }, 0); 31023 } 31024 }; 31025 function checkVal(input, writeOut, strict, nptvl, initiatingEvent) { 31026 var inputmask = this || input.inputmask, inputValue = nptvl.slice(), charCodes = "", initialNdx = -1, result = undefined; 31027 function isTemplateMatch(ndx, charCodes) { 31028 var charCodeNdx = getMaskTemplate(true, 0, false).slice(ndx, seekNext(ndx)).join("").replace(/'/g, "").indexOf(charCodes); 31029 return charCodeNdx !== -1 && !isMask(ndx) && (getTest(ndx).match.nativeDef === charCodes.charAt(0) || getTest(ndx).match.fn === null && getTest(ndx).match.nativeDef === "'" + charCodes.charAt(0) || getTest(ndx).match.nativeDef === " " && (getTest(ndx + 1).match.nativeDef === charCodes.charAt(0) || getTest(ndx + 1).match.fn === null && getTest(ndx + 1).match.nativeDef === "'" + charCodes.charAt(0))); 31030 } 31031 resetMaskSet(); 31032 if (!strict && opts.autoUnmask !== true) { 31033 var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + Inputmask.escapeRegex(staticInput), "g")); 31034 if (matches && matches.length > 0) { 31035 inputValue.splice(0, matches.length * staticInput.length); 31036 initialNdx = seekNext(initialNdx); 31037 } 31038 } else { 31039 initialNdx = seekNext(initialNdx); 31040 } 31041 if (initialNdx === -1) { 31042 getMaskSet().p = seekNext(initialNdx); 31043 initialNdx = 0; 31044 } else getMaskSet().p = initialNdx; 31045 inputmask.caretPos = { 31046 begin: initialNdx 31047 };
31048 $.each(inputValue, function(ndx, charCode) { 31049 if (charCode !== undefined) { 31050 if (getMaskSet().validPositions[ndx] === undefined && inputValue[ndx] === getPlaceholder(ndx) && isMask(ndx, true) && isValid(ndx, inputValue[ndx], true, undefined, undefined, true) === false) { 31051 getMaskSet().p++; 31052 } else { 31053 var keypress = new $.Event("_checkval"); 31054 keypress.which = charCode.charCodeAt(0); 31055 charCodes += charCode; 31056 var lvp = getLastValidPosition(undefined, true); 31057 if (!isTemplateMatch(initialNdx, charCodes)) { 31058 result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, inputmask.caretPos.begin); 31059 if (result) { 31060 initialNdx = inputmask.caretPos.begin + 1; 31061 charCodes = ""; 31062 } 31063 } else { 31064 result = EventHandlers.keypressEvent.call(input, keypress, true, false, strict, lvp + 1); 31065 } 31066 if (result) { 31067 writeBuffer(undefined, getBuffer(), result.forwardPosition, keypress, false); 31068 inputmask.caretPos = { 31069 begin: result.forwardPosition, 31070 end: result.forwardPosition 31071 }; 31072 } 31073 } 31074 } 31075 }); 31076 if (writeOut) writeBuffer(input, getBuffer(), result ? result.forwardPosition : undefined, initiatingEvent || new $.Event("checkval"), initiatingEvent && initiatingEvent.type === "input"); 31077 } 31078 function unmaskedvalue(input) { 31079 if (input) { 31080 if (input.inputmask === undefined) { 31081 return input.value; 31082 } 31083 if (input.inputmask && input.inputmask.refreshValue) { 31084 EventHandlers.setValueEvent.call(input); 31085 } 31086 } 31087 var umValue = [], vps = getMaskSet().validPositions; 31088 for (var pndx in vps) { 31089 if (vps[pndx].match && vps[pndx].match.fn != null) { 31090 umValue.push(vps[pndx].input); 31091 } 31092 } 31093 var unmaskedValue = umValue.length === 0 ? "" : (isRTL ? umValue.reverse() : umValue).join(""); 31094 if ($.isFunction(opts.onUnMask)) { 31095 var bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join(""); 31096 unmaskedValue = opts.onUnMask.call(inputmask, bufferValue, unmaskedValue, opts); 31097 } 31098 return unmaskedValue; 31099 } 31100 function caret(input, begin, end, notranslate) { 31101 function translatePosition(pos) { 31102 if (isRTL && typeof pos === "number" && (!opts.greedy || opts.placeholder !== "") && el) { 31103 pos = el.inputmask._valueGet().length - pos; 31104 } 31105 return pos; 31106 } 31107 var range; 31108 if (begin !== undefined) { 31109 if ($.isArray(begin)) { 31110 end = isRTL ? begin[0] : begin[1]; 31111 begin = isRTL ? begin[1] : begin[0]; 31112 } 31113 if (begin.begin !== undefined) { 31114 end = isRTL ? begin.begin : begin.end; 31115 begin = isRTL ? begin.end : begin.begin; 31116 } 31117 if (typeof begin === "number") { 31118 begin = notranslate ? begin : translatePosition(begin); 31119 end = notranslate ? end : translatePosition(end); 31120 end = typeof end == "number" ? end : begin; 31121 var scrollCalc = parseInt(((input.ownerDocument.defaultView || window).getComputedStyle ? (input.ownerDocument.defaultView || window).getComputedStyle(input, null) : input.currentStyle).fontSize) * end; 31122 input.scrollLeft = scrollCalc > input.scrollWidth ? scrollCalc : 0; 31123 input.inputmask.caretPos = { 31124 begin: begin, 31125 end: end 31126 }; 31127 if (input === document.activeElement) { 31128 if ("selectionStart" in input) { 31129 input.selectionStart = begin; 31130 input.selectionEnd = end; 31131 } else if (window.getSelection) { 31132 range = document.createRange(); 31133 if (input.firstChild === undefined || input.firstChild === null) { 31134 var textNode = document.createTextNode(""); 31135 input.appendChild(textNode); 31136 } 31137 range.setStart(input.firstChild, begin < input.inputmask._valueGet().length ? begin : input.inputmask._valueGet().length); 31138 range.setEnd(input.firstChild, end < input.inputmask._valueGet().length ? end : input.inputmask._valueGet().length); 31139 range.collapse(true); 31140 var sel = window.getSelection(); 31141 sel.removeAllRanges(); 31142 sel.addRange(range); 31143 } else if (input.createTextRange) { 31144 range = input.createTextRange(); 31145 range.collapse(true); 31146 range.moveEnd("character", end); 31147 range.moveStart("character", begin); 31148 range.select(); 31149 } 31150 renderColorMask(input, { 31151 begin: begin, 31152 end: end 31153 }); 31154 } 31155 } 31156 } else { 31157 if ("selectionStart" in input) { 31158 begin = input.selectionStart; 31159 end = input.selectionEnd; 31160 } else if (window.getSelection) { 31161 range = window.getSelection().getRangeAt(0); 31162 if (range.commonAncestorContainer.parentNode === input || range.commonAncestorContainer === input) { 31163 begin = range.startOffset; 31164 end = range.endOffset; 31165 } 31166 } else if (document.selection && document.selection.createRange) { 31167 range = document.selection.createRange(); 31168 begin = 0 - range.duplicate().moveStart("character", -input.inputmask._valueGet().length); 31169 end = begin + range.text.length; 31170 } 31171 return { 31172 begin: notranslate ? begin : translatePosition(begin), 31173 end: notranslate ? end : translatePosition(en
31173d) 31174 }; 31175 } 31176 } 31177 function determineLastRequiredPosition(returnDefinition) { 31178 var buffer = getMaskTemplate(true, getLastValidPosition(), true, true), bl = buffer.length, pos, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = lvTest !== undefined ? lvTest.locator.slice() : undefined, testPos; 31179 for (pos = lvp + 1; pos < buffer.length; pos++) { 31180 testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); 31181 ndxIntlzr = testPos.locator.slice(); 31182 positions[pos] = $.extend(true, {}, testPos); 31183 } 31184 var lvTestAlt = lvTest && lvTest.alternation !== undefined ? lvTest.locator[lvTest.alternation] : undefined; 31185 for (pos = bl - 1; pos > lvp; pos--) { 31186 testPos = positions[pos]; 31187 if ((testPos.match.optionality || testPos.match.optionalQuantifier && testPos.match.newBlockMarker || lvTestAlt && (lvTestAlt !== positions[pos].locator[lvTest.alternation] && testPos.match.fn != null || testPos.match.fn === null && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.toString().split(",")) && getTests(pos)[0].def !== "")) && buffer[pos] === getPlaceholder(pos, testPos.match)) { 31188 bl--; 31189 } else break; 31190 } 31191 return returnDefinition ? { 31192 l: bl, 31193 def: positions[bl] ? positions[bl].match : undefined 31194 } : bl; 31195 } 31196 function clearOptionalTail(buffer) { 31197 buffer.length = 0; 31198 var template = getMaskTemplate(true, 0, true, undefined, true), lmnt, validPos; 31199 while (lmnt = template.shift(), lmnt !== undefined) { 31200 buffer.push(lmnt); 31201 } 31202 return buffer; 31203 } 31204 function isComplete(buffer) { 31205 if ($.isFunction(opts.isComplete)) return opts.isComplete(buffer, opts); 31206 if (opts.repeat === "*") return undefined; 31207 var complete = false, lrp = determineLastRequiredPosition(true), aml = seekPrevious(lrp.l); 31208 if (lrp.def === undefined || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) { 31209 complete = true; 31210 for (var i = 0; i <= aml; i++) { 31211 var test = getTestTemplate(i).match; 31212 if (test.fn !== null && getMaskSet().validPositions[i] === undefined && test.optionality !== true && test.optionalQuantifier !== true || test.fn === null && buffer[i] !== getPlaceholder(i, test)) { 31213 complete = false; 31214 break; 31215 } 31216 } 31217 } 31218 return complete; 31219 } 31220 function handleRemove(input, k, pos, strict, fromIsValid) { 31221 if (opts.numericInput || isRTL) { 31222 if (k === Inputmask.keyCode.BACKSPACE) { 31223 k = Inputmask.keyCode.DELETE; 31224 } else if (k === Inputmask.keyCode.DELETE) { 31225 k = Inputmask.keyCode.BACKSPACE; 31226 } 31227 if (isRTL) { 31228 var pend = pos.end; 31229 pos.end = pos.begin; 31230 pos.begin = pend; 31231 } 31232 } 31233 if (k === Inputmask.keyCode.BACKSPACE && pos.end - pos.begin < 1) { 31234 pos.begin = seekPrevious(pos.begin); 31235 if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) { 31236 pos.begin--; 31237 } 31238 } else if (k === Inputmask.keyCode.DELETE && pos.begin === pos.end) { 31239 pos.end = isMask(pos.end, true) && getMaskSet().validPositions[pos.end] && getMaskSet().validPositions[pos.end].input !== opts.radixPoint ? pos.end + 1 : seekNext(pos.end) + 1; 31240 if (getMaskSet().validPositions[pos.begin] !== undefined && getMaskSet().validPositions[pos.begin].input === opts.groupSeparator) { 31241 pos.end++; 31242 } 31243 } 31244 revalidateMask(pos); 31245 if (strict !== true && opts.keepStatic !== false || opts.regex !== null) { 31246 var result = alternate(true); 31247 if (result) { 31248 var newPos = result.caret !== undefined ? result.caret : result.pos ? seekNext(result.pos.begin ? result.pos.begin : result.pos) : getLastValidPosition(-1, true); 31249 if (k !== Inputmask.keyCode.DELETE || pos.begin > newPos) { 31250 pos.begin == newPos; 31251 } 31252 } 31253 } 31254 var lvp = getLastValidPosition(pos.begin, true); 31255 if (lvp < pos.begin || pos.begin === -1) { 31256 getMaskSet().p = seekNext(lvp); 31257 } else if (strict !== true) { 31258 getMaskSet().p = pos.begin; 31259 if (fromIsValid !== true) { 31260 while (getMaskSet().p < lvp && getMaskSet().validPositions[getMaskSet().p] === undefined) { 31261 getMaskSet().p++; 31262 } 31263 } 31264 } 31265 } 31266 function initializeColorMask(input) { 31267 var computedStyle = (input.ownerDocument.defaultView || window).getComputedStyle(input, null); 31268 function findCaretPos(clientx) { 31269 var e = document.createElement("span"), caretPos; 31270 for (var style in computedStyle) { 31271 if (isNaN(style) && style.indexOf("font") !== -1) { 31272 e.style[style] = computedStyle[style]; 31273 } 31274 } 31275 e.style.textTransform = computedStyle.textTransform; 31276 e.style.letterSpacing = computedStyle.letterSpacing; 31277 e.style.position = "absolute"; 31278 e.style.height = "auto"; 31279 e.style.width = "auto"; 31280 e.style.visibility = "hidden"; 31281 e.style.whiteSpace = "nowrap"; 31282 document.body.appendChild(e); 31283 var inputText = input.inputmask._valueGet(), previousWidth = 0, itl; 31284 for (caretPos = 0, itl = inputText.length; caretPos <= itl;
31284 caretPos++) { 31285 e.innerHTML += inputText.charAt(caretPos) || "_"; 31286 if (e.offsetWidth >= clientx) { 31287 var offset1 = clientx - previousWidth; 31288 var offset2 = e.offsetWidth - clientx; 31289 e.innerHTML = inputText.charAt(caretPos); 31290 offset1 -= e.offsetWidth / 3; 31291 caretPos = offset1 < offset2 ? caretPos - 1 : caretPos; 31292 break; 31293 } 31294 previousWidth = e.offsetWidth; 31295 } 31296 document.body.removeChild(e); 31297 return caretPos; 31298 } 31299 var template = document.createElement("div"); 31300 template.style.width = computedStyle.width; 31301 template.style.textAlign = computedStyle.textAlign; 31302 colorMask = document.createElement("div"); 31303 input.inputmask.colorMask = colorMask; 31304 colorMask.className = "im-colormask"; 31305 input.parentNode.insertBefore(colorMask, input); 31306 input.parentNode.removeChild(input); 31307 colorMask.appendChild(input); 31308 colorMask.appendChild(template); 31309 input.style.left = template.offsetLeft + "px"; 31310 $(colorMask).on("mouseleave", function(e) { 31311 return EventHandlers.mouseleaveEvent.call(input, [ e ]); 31312 }); 31313 $(colorMask).on("mouseenter", function(e) { 31314 return EventHandlers.mouseenterEvent.call(input, [ e ]); 31315 }); 31316 $(colorMask).on("click", function(e) { 31317 caret(input, findCaretPos(e.clientX)); 31318 return EventHandlers.clickEvent.call(input, [ e ]); 31319 }); 31320 } 31321 function renderColorMask(input, caretPos, clear) { 31322 var maskTemplate = [], isStatic = false, test, testPos, ndxIntlzr, pos = 0; 31323 function setEntry(entry) { 31324 if (entry === undefined) entry = ""; 31325 if (!isStatic && (test.fn === null || testPos.input === undefined)) { 31326 isStatic = true; 31327 maskTemplate.push("<span class='im-static'>" + entry); 31328 } else if (isStatic && (test.fn !== null && testPos.input !== undefined || test.def === "")) { 31329 isStatic = false; 31330 var mtl = maskTemplate.length; 31331 maskTemplate[mtl - 1] = maskTemplate[mtl - 1] + "</span>"; 31332 maskTemplate.push(entry); 31333 } else maskTemplate.push(entry); 31334 } 31335 function setCaret() { 31336 if (document.activeElement === input) { 31337 maskTemplate.splice(caretPos.begin, 0, caretPos.begin === caretPos.end || caretPos.end > getMaskSet().maskLength ? '<mark class="im-caret" style="border-right-width: 1px;border-right-style: solid;">' : '<mark class="im-caret-select">'); 31338 maskTemplate.splice(caretPos.end + 1, 0, "</mark>"); 31339 } 31340 } 31341 if (colorMask !== undefined) { 31342 var buffer = getBuffer(); 31343 if (caretPos === undefined) { 31344 caretPos = caret(input); 31345 } else if (caretPos.begin === undefined) { 31346 caretPos = { 31347 begin: caretPos, 31348 end: caretPos 31349 }; 31350 } 31351 if (clear !== true) { 31352 var lvp = getLastValidPosition(); 31353 do { 31354 if (getMaskSet().validPositions[pos]) { 31355 testPos = getMaskSet().validPositions[pos]; 31356 test = testPos.match; 31357 ndxIntlzr = testPos.locator.slice(); 31358 setEntry(buffer[pos]); 31359 } else { 31360 testPos = getTestTemplate(pos, ndxIntlzr, pos - 1); 31361 test = testPos.match; 31362 ndxIntlzr = testPos.locator.slice(); 31363 if (opts.jitMasking === false || pos < lvp || typeof opts.jitMasking === "number" && isFinite(opts.jitMasking) && opts.jitMasking > pos) { 31364 setEntry(getPlaceholder(pos, test)); 31365 } else isStatic = false;
31366 } 31367 pos++; 31368 } while ((maxLength === undefined || pos < maxLength) && (test.fn !== null || test.def !== "") || lvp > pos || isStatic); 31369 if (isStatic) setEntry(); 31370 setCaret(); 31371 } 31372 var template = colorMask.getElementsByTagName("div")[0]; 31373 template.innerHTML = maskTemplate.join(""); 31374 input.inputmask.positionColorMask(input, template); 31375 } 31376 } 31377 function mask(elem) { 31378 function isElementTypeSupported(input, opts) { 31379 function patchValueProperty(npt) { 31380 var valueGet; 31381 var valueSet; 31382 function patchValhook(type) { 31383 if ($.valHooks && ($.valHooks[type] === undefined || $.valHooks[type].inputmaskpatch !== true)) { 31384 var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) { 31385 return elem.value; 31386 }; 31387 var valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) { 31388 elem.value = value; 31389 return elem; 31390 }; 31391 $.valHooks[type] = { 31392 get: function get(elem) { 31393 if (elem.inputmask) { 31394 if (elem.inputmask.opts.autoUnmask) { 31395 return elem.inputmask.unmaskedvalue(); 31396 } else { 31397 var result = valhookGet(elem); 31398 return getLastValidPosition(undefined, undefined, elem.inputmask.maskset.validPositions) !== -1 || opts.nullable !== true ? result : ""; 31399 } 31400 } else return valhookGet(elem); 31401 }, 31402 set: function set(elem, value) { 31403 var $elem = $(elem), result; 31404 result = valhookSet(elem, value); 31405 if (elem.inputmask) { 31406 $elem.trigger("setvalue", [ value ]); 31407 } 31408 return result; 31409 }, 31410 inputmaskpatch: true 31411 }; 31412 } 31413 } 31414 function getter() { 31415 if (this.inputmask) { 31416 return this.inputmask.opts.autoUnmask ? this.inputmask.unmaskedvalue() : getLastValidPosition() !== -1 || opts.nullable !== true ? document.activeElement === this && opts.clearMaskOnLostFocus ? (isRTL ? clearOptionalTail(getBuffer().slice()).reverse() : clearOptionalTail(getBuffer().slice())).join("") : valueGet.call(this) : ""; 31417 } else return valueGet.call(this); 31418 } 31419 function setter(value) { 31420 valueSet.call(this, value); 31421 if (this.inputmask) { 31422 $(this).trigger("setvalue", [ value ]); 31423 } 31424 } 31425 function installNativeValueSetFallback(npt) { 31426 EventRuler.on(npt, "mouseenter", function(event) { 31427 var $input = $(this), input = this, value = input.inputmask._valueGet(); 31428 if (value !== getBuffer().join("")) { 31429 $input.trigger("setvalue"); 31430 } 31431 }); 31432 } 31433 if (!npt.inputmask.__valueGet) { 31434 if (opts.noValuePatching !== true) { 31435 if (Object.getOwnPropertyDescriptor) { 31436 if (typeof Object.getPrototypeOf
31436!== "function") { 31437 Object.getPrototypeOf = _typeof("test".__proto__) === "object" ? function(object) { 31438 return object.__proto__; 31439 } : function(object) { 31440 return object.constructor.prototype; 31441 }; 31442 } 31443 var valueProperty = Object.getPrototypeOf ? Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt), "value") : undefined; 31444 if (valueProperty && valueProperty.get && valueProperty.set) { 31445 valueGet = valueProperty.get; 31446 valueSet = valueProperty.set; 31447 Object.defineProperty(npt, "value", { 31448 get: getter, 31449 set: setter, 31450 configurable: true 31451 }); 31452 } else if (npt.tagName !== "INPUT") { 31453 valueGet = function valueGet() { 31454 return this.textContent; 31455 }; 31456 valueSet = function valueSet(value) { 31457 this.textContent = value; 31458 }; 31459 Object.defineProperty(npt, "value", { 31460 get: getter, 31461 set: setter, 31462 configurable: true 31463 }); 31464 } 31465 } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) { 31466 valueGet = npt.__lookupGetter__("value"); 31467 valueSet = npt.__lookupSetter__("value"); 31468 npt.__defineGetter__("value", getter); 31469 npt.__defineSetter__("value", setter); 31470 } 31471 npt.inputmask.__valueGet = valueGet; 31472 npt.inputmask.__valueSet = valueSet; 31473 } 31474 npt.inputmask._valueGet = function(overruleRTL) { 31475 return isRTL && overruleRTL !== true ? valueGet.call(this.el).split("").reverse().join("") : valueGet.call(this.el); 31476 }; 31477 npt.inputmask._valueSet = function(value, overruleRTL) { 31478 valueSet.call(this.el, value === null || value === undefined ? "" : overruleRTL !== true && isRTL ? value.split("").reverse().join("") : value); 31479 }; 31480 if (valueGet === undefined) { 31481 valueGet = function valueGet() { 31482 return this.value; 31483 }; 31484 valueSet = function valueSet(value) { 31485 this.value = value; 31486 }; 31487 patchValhook(npt.type); 31488 installNativeValueSetFallback(npt); 31489 } 31490 } 31491 } 31492 var elementType = input.getAttribute("type"); 31493 var isSupported = input.tagName === "INPUT" && $.inArray(elementType, opts.supportsInputType) !== -1 || input.isContentEditable || input.tagName === "TEXTAREA"; 31494 if (!isSupported) { 31495 if (input.tagName === "INPUT") { 31496 var el = document.createElement("input"); 31497 el.setAttribute("type", elementType); 31498 isSupported = el.type === "text"; 31499 el = null; 31500 } else isSupported = "partial"; 31501 } 31502 if (isSupported !== false) { 31503 patchValueProperty(input); 31504 } else input.inputmask = undefined; 31505 return isSupported; 31506 } 31507 EventRuler.off(elem); 31508 var isSupported = isElementTypeSupported(elem, opts); 31509 if (isSupported !== false) { 31510 el = elem; 31511 $el = $(el); 31512 originalPlaceholder = el.placeholder; 31513 maxLength = el !== undefined ? el.maxLength : undefined; 31514 if (maxLength === -1) maxLength = undefined; 31515 if (opts.colorMask === true) { 31516 initializeColorMask(el); 31517 } 31518 if (mobile) { 31519 if ("inputmode" in el) { 31520 el.inputmode = opts.inputmode; 31521 el.setAttribute("inputmode", opts.inputmode); 31522 } 31523 if (opts.disablePredictiveText === true) { 31524 if ("autocorrect" in el) { 31525 el.autocorrect = false;
31526 } else { 31527 if (opts.colorMask !== true) { 31528 initializeColorMask(el); 31529 } 31530 el.type = "password"; 31531 } 31532 } 31533 } 31534 if (isSupported === true) { 31535 el.setAttribute("im-insert", opts.insertMode); 31536 EventRuler.on(el, "submit", EventHandlers.submitEvent); 31537 EventRuler.on(el, "reset", EventHandlers.resetEvent); 31538 EventRuler.on(el, "blur", EventHandlers.blurEvent); 31539 EventRuler.on(el, "focus", EventHandlers.focusEvent); 31540 if (opts.colorMask !== true) { 31541 EventRuler.on(el, "click", EventHandlers.clickEvent); 31542 EventRuler.on(el, "mouseleave", EventHandlers.mouseleaveEvent); 31543 EventRuler.on(el, "mouseenter", EventHandlers.mouseenterEvent); 31544 } 31545 EventRuler.on(el, "paste", EventHandlers.pasteEvent); 31546 EventRuler.on(el, "cut", EventHandlers.cutEvent); 31547 EventRuler.on(el, "complete", opts.oncomplete); 31548 EventRuler.on(el, "incomplete", opts.onincomplete); 31549 EventRuler.on(el, "cleared", opts.oncleared); 31550 if (!mobile && opts.inputEventOnly !== true) { 31551 EventRuler.on(el, "keydown", EventHandlers.keydownEvent); 31552 EventRuler.on(el, "keypress", EventHandlers.keypressEvent); 31553 } else { 31554 el.removeAttribute("maxLength"); 31555 } 31556 EventRuler.on(el, "input", EventHandlers.inputFallBackEvent); 31557 EventRuler.on(el, "beforeinput", EventHandlers.beforeInputEvent); 31558 } 31559 EventRuler.on(el, "setvalue", EventHandlers.setValueEvent); 31560 undoValue = getBufferTemplate().join(""); 31561 if (el.inputmask._valueGet(true) !== "" || opts.clearMaskOnLostFocus === false || document.activeElement === el) { 31562 var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, el.inputmask._valueGet(true), opts) || el.inputmask._valueGet(true) : el.inputmask._valueGet(true); 31563 if (initialValue !== "") checkVal(el, true, false, initialValue.split("")); 31564 var buffer = getBuffer().slice(); 31565 undoValue = buffer.join(""); 31566 if (isComplete(buffer) === false) { 31567 if (opts.clearIncomplete) { 31568 resetMaskSet(); 31569 } 31570 } 31571 if (opts.clearMaskOnLostFocus && document.activeElement !== el) { 31572 if (getLastValidPosition() === -1) { 31573 buffer = []; 31574 } else { 31575 clearOptionalTail(buffer); 31576 } 31577 } 31578 if (opts.clearMaskOnLostFocus === false || opts.showMaskOnFocus && document.activeElement === el || el.inputmask._valueGet(true) !== "") writeBuffer(el, buffer); 31579 if (document.activeElement === el) { 31580 caret(el, seekNext(getLastValidPosition())); 31581 } 31582 } 31583 } 31584 } 31585 var valueBuffer; 31586 if (actionObj !== undefined) { 31587 switch (actionObj.action) { 31588 case "isComplete": 31589 el = actionObj.el; 31590 return isComplete(getBuffer()); 31591 31592 case "unmaskedvalue": 31593 if (el === undefined || actionObj.value !== undefined) { 31594 valueBuffer = actionObj.value; 31595 valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, valueBuffer, opts) || valueBuffer : valueBuffer).split(""); 31596 checkVal.call(this, undefined, false, false, valueBuffer); 31597 if ($.isFunction(opts.onBeforeWrite)) opts.onBeforeWrite.call(inputmask, undefined, getBuffer(), 0, opts); 31598 } 31599 return unmaskedvalue(el); 31600 31601 case "mask": 31602 mask(el); 31603 break; 31604 31605 case "format": 31606 valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(inputmask, actionObj.value, opts) || actionObj.value : actionObj.value).split(""); 31607 checkVal.call(this, undefined, true, false, valueBuffer); 31608 if (actionObj.metadata) { 31609 return { 31610 value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""), 31611 metadata: maskScope.call(this, { 31612 action: "getmetadata" 31613 }, maskset, opts) 31614 }; 31615 } 31616 return isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""); 31617 31618 case "isValid": 31619 if (actionObj.value) { 31620 valueBuffer = actionObj.value.split(""); 31621 checkVal.call(this, undefined, true, true, valueBuffer); 31622 } else { 31623 actionObj.value = getBuffer().join(""); 31624 } 31625 var buffer = getBuffer(); 31626 var rl = determineLastRequiredPosition(), lmib = buffer.length - 1; 31627 for (;lmib > rl; lmib--) { 31628 if (isMask(lmib)) break; 31629 } 31630 buffer.splice(rl, lmib + 1 - rl); 31631 return isComplete(buffer) && actionObj.value === getBuffer().join(""); 31632 31633 case "getemptymask": 31634 return getBufferTemplate().join(""); 31635 31636 case "remove": 31637 if (el && el.inputmask) { 31638 $.data(el, "_inputmask_opts", null); 31639 $el = $(el); 31640 el.inputmask._valueSet(opts.autoUnmask ? unmaskedvalue(el) : el.inputmask._valueGet(true)); 31641 EventRuler.off(el); 31642 if (el.inputmask.colorMask) { 31643 colorMask = el.inputmask.colorMask; 31644 colorMask.removeChild(el); 31645 colorMask.parentNode.insertBefore(el, colorMask); 31646 colorMask.parentNode.removeChild(colorMask); 31647 } 31648 var valueProperty; 31649 if (Object.getOwnPropertyDescriptor && Ob
31649ject.getPrototypeOf) { 31650 valueProperty = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value"); 31651 if (valueProperty) { 31652 if (el.inputmask.__valueGet) { 31653 Object.defineProperty(el, "value", { 31654 get: el.inputmask.__valueGet, 31655 set: el.inputmask.__valueSet, 31656 configurable: true 31657 }); 31658 } 31659 } 31660 } else if (document.__lookupGetter__ && el.__lookupGetter__("value")) { 31661 if (el.inputmask.__valueGet) { 31662 el.__defineGetter__("value", el.inputmask.__valueGet); 31663 el.__defineSetter__("value", el.inputmask.__valueSet); 31664 } 31665 } 31666 el.inputmask = undefined; 31667 } 31668 return el; 31669 break; 31670 31671 case "getmetadata": 31672 if ($.isArray(maskset.metadata)) { 31673 var maskTarget = getMaskTemplate(true, 0, false).join(""); 31674 $.each(maskset.metadata, function(ndx, mtdt) { 31675 if (mtdt.mask === maskTarget) { 31676 maskTarget = mtdt; 31677 return false; 31678 } 31679 }); 31680 return maskTarget; 31681 } 31682 return maskset.metadata; 31683 } 31684 } 31685 } 31686 return Inputmask; 31687 }); 31688}, function(module, exports, __webpack_require__) { 31689 "use strict"; 31690 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 31691 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 31692 return typeof obj; 31693 } : function(obj) { 31694 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 31695 }; 31696 (function(factory) { 31697 if (true) { 31698 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 31699 __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 31700 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 31701 } else {} 31702 })(function($) { 31703 return $; 31704 }); 31705}, function(module, exports) { 31706 module.exports = jQuery; 31707}, function(module, exports, __webpack_require__) { 31708 "use strict"; 31709 var __WEBPACK_AMD_DEFINE_RESULT__; 31710 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 31711 return typeof obj; 31712 } : function(obj) { 31713 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 31714 }; 31715 if (true) !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { 31716 return typeof window !== "undefined" ? window : new (eval("require('jsdom').JSDOM"))("").window; 31717 }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); else {} 31718}, function(module, exports, __webpack_require__) { 31719 "use strict"; 31720 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 31721 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 31722 return typeof obj; 31723 } : function(obj) { 31724 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 31725 }; 31726 (function(factory) { 31727 if (true) { 31728 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 31729 __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 31730 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 31731 } else {} 31732 })(function(Inputmask) { 31733 var $ = Inputmask.dependencyLib; 31734 var formatCode = { 31735 d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ], 31736 dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() { 31737 return pad(Date.prototype.getDate.call(this), 2); 31738 } ], 31739 ddd: [ "" ], 31740 dddd: [ "" ], 31741 m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() { 31742 return Date.prototype.getMonth.call(this) + 1; 31743 } ], 31744 mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() { 31745 return pad(Date.prototype.getMonth.call(this) + 1, 2); 31746 } ], 31747 mmm: [ "" ], 31748 mmmm: [ "" ], 31749 yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() { 31750 return pad(Date.prototype.getFullYear.call(this), 2); 31751 } ], 31752 yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() { 31753 return pad(Date.prototype.getFullYear.call(this), 4); 31754 } ], 31755 h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ], 31756 hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() { 31757 return pad(Date.prototype.getHours.call(this), 2); 31758 } ], 31759 hhh: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ], 31760 H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ], 31761 HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() { 31762 return pad(Date.prototype.getHours.call(this), 2); 31763 } ], 31764 HHH: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ], 31765 M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ], 31766 MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() { 31767 return pad(Date.prototype.getMinutes.call(this), 2); 31768 } ], 31769 ss: [ "[0-5][0-9]", Date.prototype.setSeconds, "seconds", function() { 31770 return pad(Date.prototype.getSeconds.call(this), 2); 31771 } ], 31772 l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() { 31773 return pad(Date.prototype.getMilliseconds.call(this), 3); 31774 } ], 31775 L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() { 31776 return pad(Date.prototype.getMilliseconds.call(this), 2); 31777 } ], 31778 t: [ "[ap]" ], 31779 tt: [ "[ap]m" ], 31780 T: [ "[AP]" ], 31781 TT: [ "[AP]M" ], 31782 Z: [ "" ], 31783 o: [ "" ], 31784 S: [ "" ] 31785 }, formatAlias = { 31786 isoDate: "yyyy-mm-dd", 31787 isoTime: "HH:MM:ss", 31788 isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", 31789 isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" 31790 }; 31791 function getTokenizer(opts) { 31792 if (!opts.tokenizer) { 31793 var tokens = []; 31794 for (var ndx in formatCode) { 31795 if (tokens.indexOf(ndx[0]) === -1) tokens.push(ndx[0]); 31796 } 31797 opts.tokenizer = "(" + tokens.join("+|") + ")+?|."; 31798 opts.tokenizer = new RegExp(opts.tokenizer, "g"); 31799 } 31800 return opts.tokenizer; 31801 } 31802 function isValidDate(dateParts, currentResult) { 31803 return !isFinite(dateParts.rawday) || dateParts.day == "29" && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day ? currentResult : false;
31804 } 31805 function isDateInRange(dateParts, opts) { 31806 var result = true; 31807 if (opts.min) { 31808 if (dateParts["rawyear"]) { 31809 var rawYear = dateParts["rawyear"].replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length); 31810 result = minYear <= rawYear; 31811 } 31812 if (dateParts["year"] === dateParts["rawyear"]) { 31813 if (opts.min.date.getTime() === opts.min.date.getTime()) { 31814 result = opts.min.date.getTime() <= dateParts.date.getTime(); 31815 } 31816 } 31817 } 31818 if (result && opts.max && opts.max.date.getTime() === opts.max.date.getTime()) { 31819 result = opts.max.date.getTime() >= dateParts.date.getTime(); 31820 } 31821 return result; 31822 } 31823 function parse(format, dateObjValue, opts, raw) { 31824 var mask = "", match; 31825 while (match = getTokenizer(opts).exec(format)) { 31826 if (dateObjValue === undefined) { 31827 if (formatCode[match[0]]) { 31828 mask += "(" + formatCode[match[0]][0] + ")"; 31829 } else { 31830 switch (match[0]) { 31831 case "[": 31832 mask += "("; 31833 break; 31834 31835 case "]": 31836 mask += ")?"; 31837 break; 31838 31839 default: 31840 mask += Inputmask.escapeRegex(match[0]); 31841 } 31842 } 31843 } else { 31844 if (formatCode[match[0]]) { 31845 if (raw !== true && formatCode[match[0]][3]) { 31846 var getFn = formatCode[match[0]][3]; 31847 mask += getFn.call(dateObjValue.date); 31848 } else if (formatCode[match[0]][2]) mask += dateObjValue["raw" + formatCode[match[0]][2]]; else mask += match[0]; 31849 } else mask += match[0]; 31850 } 31851 } 31852 return mask; 31853 } 31854 function pad(val, len) { 31855 val = String(val); 31856 len = len || 2; 31857 while (val.length < len) { 31858 val = "0" + val; 31859 } 31860 return val; 31861 } 31862 function analyseMask(maskString, format, opts) { 31863 var dateObj = { 31864 date: new Date(1, 0, 1) 31865 }, targetProp, mask = maskString, match, dateOperation, targetValidator; 31866 function extendProperty(value) { 31867 var correctedValue = value.replace(/[^0-9]/g, "0"); 31868 if (correctedValue != value) { 31869 var enteredPart = value.replace(/[^0-9]/g, ""), min = (opts.min && opts.min[targetProp] || value).toString(), max = (opts.max && opts.max[targetProp] || value).toString(); 31870 correctedValue = enteredPart + (enteredPart < min.slice(0, enteredPart.length) ? min.slice(enteredPart.length) : enteredPart > max.slice(0, enteredPart.length) ? max.slice(enteredPart.length) : correctedValue.toString().slice(enteredPart.length)); 31871 } 31872 return correctedValue; 31873 } 31874 function setValue(dateObj, value, opts) { 31875 dateObj[targetProp] = extendProperty(value); 31876 dateObj["raw" + targetProp] = value; 31877 if (dateOperation !== undefined) dateOperation.call(dateObj.date, targetProp == "month" ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]); 31878 } 31879 if (typeof mask === "string") { 31880 while (match = getTokenizer(opts).exec(format)) { 31881 var value = mask.slice(0, match[0].length); 31882 if (formatCode.hasOwnProperty(match[0])) { 31883 targetValidator = formatCode[match[0]][0]; 31884 targetProp = formatCode[match[0]][2]; 31885 dateOperation = formatCode[match[0]][1]; 31886 setValue(dateObj, value, opts); 31887 } 31888 mask = mask.slice(value.length); 31889 } 31890 return dateObj; 31891 } else if (mask && (typeof mask === "undefined" ? "undefined" : _typeof(mask)) === "object" && mask.hasOwnProperty("date")) { 31892 return mask; 31893 } 31894 return undefined; 31895 } 31896 Inputmask.extendAliases({ 31897 datetime: { 31898 mask: function mask(opts) { 31899 formatCode.S = opts.i18n.ordinalSuffix.join("|"); 31900 opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat; 31901 opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat; 31902 opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat; 31903 opts.placeholder = opts.placeholder !== "" ? opts.placeholder : opts.inputFormat.replace(/[\[\]]/, ""); 31904 opts.regex = parse(opts.inputFormat, undefined, opts); 31905 return null; 31906 }, 31907 placeholder: "", 31908 inputFormat: "isoDateTime", 31909 displayFormat: undefined, 31910 outputFormat: undefined, 31911 min: null, 31912 max: null, 31913 i18n: { 31914 dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ], 31915 monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
31915November", "December" ], 31916 ordinalSuffix: [ "st", "nd", "rd", "th" ] 31917 }, 31918 postValidation: function postValidation(buffer, pos, currentResult, opts) { 31919 opts.min = analyseMask(opts.min, opts.inputFormat, opts); 31920 opts.max = analyseMask(opts.max, opts.inputFormat, opts); 31921 var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts); 31922 if (result && dateParts.date.getTime() === dateParts.date.getTime()) { 31923 result = isValidDate(dateParts, result); 31924 result = result && isDateInRange(dateParts, opts); 31925 } 31926 if (pos && result && currentResult.pos !== pos) { 31927 return { 31928 buffer: parse(opts.inputFormat, dateParts, opts), 31929 refreshFromBuffer: { 31930 start: pos, 31931 end: currentResult.pos 31932 } 31933 }; 31934 } 31935 return result; 31936 }, 31937 onKeyDown: function onKeyDown(e, buffer, caretPos, opts) { 31938 var input = this; 31939 if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) { 31940 var today = new Date(), match, date = ""; 31941 while (match = getTokenizer(opts).exec(opts.inputFormat)) { 31942 if (match[0].charAt(0) === "d") { 31943 date += pad(today.getDate(), match[0].length); 31944 } else if (match[0].charAt(0) === "m") { 31945 date += pad(today.getMonth() + 1, match[0].length); 31946 } else if (match[0] === "yyyy") { 31947 date += today.getFullYear().toString(); 31948 } else if (match[0].charAt(0) === "y") { 31949 date += pad(today.getYear(), match[0].length); 31950 } 31951 } 31952 input.inputmask._valueSet(date); 31953 $(input).trigger("setvalue"); 31954 } 31955 }, 31956 onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) { 31957 return parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, true); 31958 }, 31959 casing: function casing(elem, test, pos, validPositions) { 31960 if (test.nativeDef.indexOf("[ap]") == 0) return elem.toLowerCase(); 31961 if (test.nativeDef.indexOf("[AP]") == 0) return elem.toUpperCase(); 31962 return elem; 31963 }, 31964 insertMode: false, 31965 shiftPositions: false 31966 } 31967 }); 31968 return Inputmask; 31969 }); 31970}, function(module, exports, __webpack_require__) { 31971 "use strict"; 31972 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 31973 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 31974 return typeof obj; 31975 } : function(obj) { 31976 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 31977 }; 31978 (function(factory) { 31979 if (true) { 31980 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = factory, 31981 __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 31982 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 31983 } else {} 31984 })(function(Inputmask) { 31985 var $ = Inputmask.dependencyLib; 31986 function autoEscape(txt, opts) { 31987 var escapedTxt = ""; 31988 for (var i = 0; i < txt.length; i++) { 31989 if (Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i)) { 31990 escapedTxt += "\\" + txt.charAt(i); 31991 } else escapedTxt += txt.charAt(i); 31992 } 31993 return escapedTxt; 31994 } 31995 function alignDigits(buffer, digits, opts) { 31996 if (digits > 0) { 31997 var radixPosition = $.inArray(opts.radixPoint, buffer); 31998 if (radixPosition === -1) { 31999 buffer.push(opts.radixPoint); 32000 radixPosition = buffer.length - 1; 32001 } 32002 for (var i = 1; i <= digits; i++) { 32003 buffer[radixPosition + i] = buffer[radixPosition + i] || "0"; 32004 } 32005 } 32006 return buffer; 32007 } 32008 Inputmask.extendAliases({ 32009 numeric: { 32010 mask: function mask(opts) { 32011 if (opts.repeat !== 0 && isNaN(opts.integerDigits)) { 32012 opts.integerDigits = opts.repeat; 32013 } 32014 opts.repeat = 0; 32015 if (opts.groupSeparator === opts.radixPoint && opts.digits && opts.digits !== "0") { 32016 if (opts.radixPoint === ".") { 32017 opts.groupSeparator = ","; 32018 } else if (opts.radixPoint === ",") { 32019 opts.groupSeparator = "."; 32020 } else opts.groupSeparator = ""; 32021 } 32022 if (opts.groupSeparator === " ") { 32023 opts.skipOptionalPartCharacter = undefined; 32024 } 32025 opts.autoGroup = opts.autoGroup && opts.groupSeparator !== ""; 32026 if (opts.autoGroup) { 32027 if (typeof opts.groupSize == "string" && isFinite(opts.groupSize)) opts.groupSize = parseInt(opts.groupSize); 32028 if (isFinite(opts.integerDigits)) { 32029 var seps = Math.floor(opts.integerDigits / opts.groupSize); 32030 var mod = opts.integerDigits % opts.groupSize; 32031 opts.integerDigits = parseInt(opts.integerDigits) + (mod === 0 ? seps - 1 : seps); 32032 if (opts.integerDigits < 1) { 32033 opts.integerDigits = "*"; 32034 } 32035 } 32036 } 32037 if (opts.placeholder.length > 1) { 32038 opts.placeholder = opts.placeholder.charAt(0); 32039 } 32040 if (opts.positionCaretOnClick === "radixFocus" && opts.placeholder === "" && opts.integerOptional === false) { 32041 opts.positionCaretOnClick = "lvp"; 32042 } 32043 opts.definitions[";"] = opts.definitions["~"]; 32044 opts.definitions[";"].definitionSymbol = "~"; 32045 if (opts.numericInput === true) { 32046 opts.positionCaretOnClick = opts.positionCaretOnClick === "radixFocus" ? "lvp" : opts.positionCaretOnClick; 32047 opts.digitsOptional = false;
32048 if (isNaN(opts.digits)) opts.digits = 2; 32049 opts.decimalProtect = false; 32050 } 32051 var mask = "[+]"; 32052 mask += autoEscape(opts.prefix, opts); 32053 if (opts.integerOptional === true) { 32054 mask += "~{1," + opts.integerDigits + "}"; 32055 } else mask += "~{" + opts.integerDigits + "}"; 32056 if (opts.digits !== undefined) { 32057 var radixDef = opts.decimalProtect ? ":" : opts.radixPoint; 32058 var dq = opts.digits.toString().split(","); 32059 if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) { 32060 mask += radixDef + ";{" + opts.digits + "}"; 32061 } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) { 32062 if (opts.digitsOptional) { 32063 mask += "[" + radixDef + ";{1," + opts.digits + "}]"; 32064 } else mask += radixDef + ";{" + opts.digits + "}"; 32065 } 32066 } 32067 mask += autoEscape(opts.suffix, opts); 32068 mask += "[-]"; 32069 opts.greedy = false; 32070 return mask; 32071 }, 32072 placeholder: "", 32073 greedy: false, 32074 digits: "*", 32075 digitsOptional: true, 32076 enforceDigitsOnBlur: false, 32077 radixPoint: ".", 32078 positionCaretOnClick: "radixFocus", 32079 groupSize: 3, 32080 groupSeparator: "", 32081 autoGroup: false, 32082 allowMinus: true, 32083 negationSymbol: { 32084 front: "-", 32085 back: "" 32086 }, 32087 integerDigits: "+", 32088 integerOptional: true, 32089 prefix: "", 32090 suffix: "", 32091 rightAlign: true, 32092 decimalProtect: true, 32093 min: null, 32094 max: null, 32095 step: 1, 32096 insertMode: true, 32097 autoUnmask: false, 32098 unmaskAsNumber: false, 32099 inputType: "text", 32100 inputmode: "numeric", 32101 preValidation: function preValidation(buffer, pos, c, isSelection, opts, maskset) { 32102 if (c === "-" || c === opts.negationSymbol.front) { 32103 if (opts.allowMinus !== true) return false; 32104 opts.isNegative = opts.isNegative === undefined ? true : !opts.isNegative; 32105 if (buffer.join("") === "") return true; 32106 return { 32107 caret: maskset.validPositions[pos] ? pos : undefined, 32108 dopost: true 32109 }; 32110 } 32111 if (isSelection === false && c === opts.radixPoint && opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0)) { 32112 var radixPos = $.inArray(opts.radixPoint, buffer); 32113 if (radixPos !== -1 && maskset.validPositions[radixPos] !== undefined) { 32114 if (opts.numericInput === true) { 32115 return pos === radixPos; 32116 } 32117 return { 32118 caret: radixPos + 1 32119 }; 32120 } 32121 } 32122 return true; 32123 }, 32124 postValidation: function postValidation(buffer, pos, currentResult, opts) { 32125 function buildPostMask(buffer, opts) { 32126 var postMask = ""; 32127 postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}"; 32128 if (opts.radixPoint !== "") { 32129 var radixSplit = buffer.join("").split(opts.radixPoint); 32130 if (radixSplit[1]) { 32131 postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}"; 32132 } 32133 } 32134 return postMask; 32135 } 32136 var suffix = opts.suffix.split(""), prefix = opts.prefix.split(""); 32137 if (currentResult.pos === undefined && currentResult.caret !== undefined && currentResult.dopost !== true) return currentResult; 32138 var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos; 32139 var maskedValue = buffer.slice(); 32140 if (opts.numericInput) { 32141 caretPos = maskedValue.length - caretPos - 1; 32142 maskedValue = maskedValue.reverse(); 32143 } 32144 var charAtPos = maskedValue[caretPos]; 32145 if (charAtPos === opts.groupSeparator) { 32146 caretPos += 1; 32147 charAtPos = maskedValue[caretPos]; 32148 } 32149 if (caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult; 32150 if (charAtPos !== undefined) { 32151 if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) { 32152 maskedValue[caretPos] = "?"; 32153 if (opts.prefix.length > 0 && caretPos >= (opts.isNegative === false ? 1 : 0) && caretPos < opts.prefix.length - 1 + (opts.isNegative === false ? 1 : 0)) { 32154 prefix[caretPos - (opts.isNegative === false ? 1 : 0)] = "?"; 32155 } else if (opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0)) { 32156 suffix[caretPos - (maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0))] = "?"; 32157 } 32158 } 32159 } 32160 prefix = prefix.join(""); 32161 suffix = suffix.join(""); 32162 var processValue = maskedValue.join("").replace(prefix, ""); 32163 processValue = processValue.replace(suffix, ""); 32164 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 32165 processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""); 32166 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 32167 if (isNaN(opts.placeholder)) { 32168 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), ""); 32169 } 32170 if (processValue.length > 1 && processValue.indexOf(opts.radixPoint) !== 1) { 32171 if (charAtPos === "0") { 32172 processValue = processValue.replace(/^\?/g, ""); 32173 } 32174 processValue = processValue.replace(/^0/g, ""); 32175 } 32176 if (processValue.charAt(0) === opts.radixPoint && opts.radixPoint !== "" && opts.numericInput !== true) { 32177 processValue = "0" + processValue; 32178 } 32179 if (processValue !== "") { 32180 processValue = processValue.split(""); 32181 if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && isFinite(opts.digits)) { 32182 var radixPosition = $.inArray(opts.radixPoint, processValue); 32183 var rpb = $.inArray(opts.radixPoint, maskedValue); 32184 if (radixPosition === -1) { 32185 processValue.push(opts.radixPoint); 32186 radixPosition = processValue.length - 1; 32187 } 32188 for (var i = 1; i <= opts.digits; i++) { 32189 if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && (processValue[radixPosition + i] === undefined || processValue[radixPosition + i] === opts.placeholder.charAt(0))) { 32190 processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0); 32191 } else if (rpb !== -1 && maskedValue[rpb + i] !== undefined) { 32192 processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i]; 32193 } 32194 } 32195 } 32196 if (opts.autoGroup === true && opts.groupSeparator !== "" && (charAtPos !== opts.radixPoint || currentResult.pos !== undefined || currentResult.dopost)) { 32197 var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint; 32198 processValue = Inputmask(buildPostMask(processValue, opts), { 32199 numericInput: true, 32200 jitMasking: true, 32201 definitions: { 32202 "*": { 32203 validator: "[0-9?]", 32204 cardinality: 1 32205 } 32206 } 32207 }).format(processValue.join("")); 32208 if (addRadix) processValue += opts.radixPoint; 32209 if (processValue.charAt(0) === opts.groupSeparator) { 32210 processValue.substr(1); 32211 } 32212 } else processValue = processValue.join(""); 32213 } 32214 if (opts.isNegative && currentResult.event === "blur") { 32215 opts.isNegative = processValue !== "0"; 32216 } 32217 processValue = prefix + processValue; 32218 processValue += suffix; 32219 if (opts.isNegative) { 32220 processValue = opts.negationSymbol.front + processValue; 32221 processValue += opts.negationSymbol.back; 32222 } 32223 processValue = processValue.split(""); 32224 if (charAtPos !== undefined) { 32225 if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) { 32226 caretPos = $.inArray("?", processValue); 32227 if (caretPos > -1) { 32228 processValue[caretPos] = charAtPos; 32229 } else caretPos = currentResult.caret || 0; 32230 } else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) { 32231 var newCaretPos = $.inArray(charAtPos, processValue); 32232 if (newCaretPos !== -1) caretPos = newCaretPos; 32233 } 32234 } 32235 if (opts.numericInput) { 32236 caretPos = processValue.length - caretPos - 1; 32237 processValue = processValue.reverse(); 32238 } 32239 var rslt = { 32240 caret: (charAtPos === undefined || currentResult.pos !== undefined) && caretPos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos, 32241 buffer: processValue, 32242 refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("") 32243 }; 32244 return rslt.refreshFromBuffer ? rslt : currentResult; 32245 }, 32246 onBeforeWrite: function onBeforeWrite(e, buffer, caretPos, opts) { 32247 function parseMinMaxOptions(opts) { 32248 if (opts.parseMinMaxOptions === undefined) { 32249 if (opts.min !== null) { 32250 opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 32251 if (opts.radixPoint === ",") opts.min = opts.min.replace(opts.radixPoint, "."); 32252 opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN; 32253 if (isNaN(opts.min)) opts.min = Number.MIN_VALUE; 32254 } 32255 if (opts.max !== null) { 32256 opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 32257 if (opts.radixPoint === ",") opts.max = opts.max.replace(opts.radixPoint, "."); 32258 opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN; 32259 if (isNaN(opts.max)) opts.max = Number.MAX_VALUE; 32260 } 32261 opts.parseMinMaxOptions = "done"; 32262 } 32263 } 32264 if (e) { 32265 switch (e.type) { 32266 case "keydown": 32267 return opts.postValidation(buffer, caretPos, { 32268 caret: caretPos, 32269 dopost: true 32270 }, opts); 32271 32272 case "blur": 32273 case "checkval": 32274 var unmasked; 32275 parseMinMaxOptions(opts); 32276 if (opts.min !== null || opts.max !== null) { 32277 unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, { 32278 unmaskAsNumber: true 32279 })); 32280 if (opts.min !== null && unmasked < opts.min) { 32281 opts.isNegative = opts.min < 0; 32282 return opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), caretPos, { 32283 caret: caretPos, 32284 dopost: true, 32285 placeholder: "0" 32286 }, opts); 32287 } else if (opts.max !== null && unmasked > opts.max) { 32288 opts.isNegative = opts.max < 0; 32289 return opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), caretPos, { 32290 caret: caretPos, 32291 dopost: true, 32292 placeholder: "0" 32293 }, opts); 32294 } 32295 } 32296 return opts.postValidation(buffer, caretPos, { 32297 caret: caretPos, 32298 placeholder: "0", 32299 event: "blur" 32300 }, opts); 32301 32302 case "_checkval": 32303 return { 32304 caret: caretPos 32305 }; 32306 32307 default: 32308 break; 32309 } 32310 } 32311 }, 32312 regex: { 32313 integerPart: function integerPart(opts, emptyCheck) { 32314 return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+"); 32315 }, 32316 integerNPart: function integerNPart(opts) { 32317 return new RegExp("[\\d" + Inputmask.escapeRegex(opts.
32317groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+"); 32318 } 32319 }, 32320 definitions: { 32321 "~": { 32322 validator: function validator(chrs, maskset, pos, strict, opts, isSelection) { 32323 var isValid, l; 32324 if (chrs === "k" || chrs === "m") { 32325 isValid = { 32326 insert: [], 32327 c: 0 32328 }; 32329 for (var i = 0, l = chrs === "k" ? 2 : 5; i < l; i++) { 32330 isValid.insert.push({ 32331 pos: pos + i, 32332 c: 0 32333 }); 32334 } 32335 isValid.pos = pos + l; 32336 return isValid; 32337 } 32338 isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs); 32339 if (isValid === true) { 32340 if (opts.numericInput !== true && maskset.validPositions[pos] !== undefined && maskset.validPositions[pos].match.def === "~" && !isSelection) { 32341 var processValue = maskset.buffer.join(""); 32342 processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""); 32343 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 32344 var pvRadixSplit = processValue.split(opts.radixPoint); 32345 if (pvRadixSplit.length > 1) { 32346 pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0)); 32347 } 32348 if (pvRadixSplit[0] === "0") { 32349 pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0)); 32350 } 32351 processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || ""; 32352 var bufferTemplate = maskset._buffer.join(""); 32353 if (processValue === opts.radixPoint) { 32354 processValue = bufferTemplate; 32355 } 32356 while (processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$") === null) { 32357 bufferTemplate = bufferTemplate.slice(1); 32358 } 32359 processValue = processValue.replace(bufferTemplate, ""); 32360 processValue = processValue.split(""); 32361 if (processValue[pos] === undefined) { 32362 isValid = { 32363 pos: pos, 32364 remove: pos 32365 }; 32366 } else { 32367 isValid = { 32368 pos: pos 32369 }; 32370 } 32371 } 32372 } else if (!strict && chrs === opts.radixPoint && maskset.validPositions[pos - 1] === undefined) { 32373 isValid = { 32374 insert: { 32375 pos: pos, 32376 c: 0 32377 }, 32378 pos: pos + 1 32379 }; 32380 } 32381 return isValid; 32382 }, 32383 cardinality: 1 32384 }, 32385 "+": { 32386 validator: function validator(chrs, maskset, pos, strict, opts) { 32387 return opts.allowMinus && (chrs === "-" || chrs === opts.negationSymbol.front); 32388 }, 32389 cardinality: 1, 32390 placeholder: "" 32391 }, 32392 "-": { 32393 validator: function validator(chrs, maskset, pos, strict, opts) { 32394 return opts.allowMinus && chrs === opts.negationSymbol.back; 32395 }, 32396 cardinality: 1, 32397 placeholder: "" 32398 }, 32399 ":": { 32400 validator: function validator(chrs, maskset, pos, strict, opts) { 32401 var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]"; 32402 var isValid = new RegExp(radix).test(chrs); 32403 if (isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint) { 32404 isValid = { 32405 caret: pos + 1 32406 }; 32407 } 32408 return isValid; 32409 }, 32410 cardinality: 1, 32411 placeholder: function placeholder(opts) { 32412 return opts.radixPoint; 32413 } 32414 } 32415 }, 32416 onUnMask: function onUnMask(maskedValue, unmaskedValue, opts) { 32417 if (unmaskedValue === "" && opts.nullable === true) { 32418 return unmaskedValue; 32419 } 32420 var processValue = maskedValue.replace(opts.prefix, ""); 32421 processValue = processValue.replace(opts.suffix, ""); 32422 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 32423 if (opts.placeholder.charAt(0) !== "") { 32424 processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0"); 32425 } 32426 if (opts.unmaskAsNumber) { 32427 if (opts.radixPoint !== "" && processValue.indexOf(opts.radixPoint) !== -1) processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), "."); 32428 processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"); 32429 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 32430 return Number(processValue); 32431 } 32432 return processValue; 32433 }, 32434 isComplete: function isComplete(buffer, opts) { 32435 var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join(""); 32436 maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"); 32437 maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 32438 maskedValue = maskedValue.replace(opts.prefix, ""); 32439 maskedValue = maskedValue.replace(opts.suffix, ""); 32440 maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1"); 32441 if (opts.radixPoint === ",") maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), "."); 32442 return isFinite(maskedValue); 32443 }, 32444 onBeforeMask: function onBeforeMask(initialValue, opts) { 32445 opts.isNegative = undefined; 32446 var radixPoint = opts.radixPoint || ","; 32447 if ((typeof initialValue == "number" || opts.inputType === "number") && radixPoint !== "") { 32448 initialValue = initialValue.toString().replace(".", radixPoint); 32449 } 32450 var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, "") : ""; 32451 initialValue = integerPart + (decimalPart !== "" ? radixPoint + decimalPart : decimalPart); 32452 var digits = 0; 32453 if (radixPoint !== "") { 32454 digits = decimalPart.length; 32455 if (decimalPart !== "") { 32456 var digitsFactor = Math.pow(10, digits || 1); 32457 if (isFinite(opts.digits)) { 32458 digits = parseInt(opts.digits); 32459 digitsFactor = Math.pow(10, digits); 32460 } 32461 initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), "."); 32462 if (isFinite(initialValue)) initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor; 32463 initialValue = initialValue.toString().replace(".", radixPoint); 32464 } 32465 } 32466 if (opts.digits === 0 && initialValue.indexOf(Inputmask.escapeRegex(radixPoint)) !== -1) { 32467 initialValue = initialValue.substring(0, initialValue.indexOf(Inputmask.escapeRegex(radixPoint))); 32468 } 32469 return alignDigits(initialValue.toString().split(""), digits, opts).join(""); 32470 }, 32471 onKeyDown: function onKeyDown(e, buffer, caretPos, opts) { 32472 var $input = $(this); 32473 if (e.ctrlKey) { 32474 switch (e.keyCode) { 32475 case Inputmask.keyCode.UP: 32476 $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)); 32477 $input.trigger("setvalue"); 32478 break; 32479 32480 case Inputmask.keyCode.DOWN: 32481 $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)); 32482 $input.trigger("setvalue"); 32483 break; 32484 } 32485 } 32486 } 32487 }, 32488 currency: { 32489 prefix: "$ ", 32490 groupSeparator: ",", 32491 alias: "numeric", 32492 placeholder: "0", 32493 autoGroup: true, 32494 digits: 2, 32495 digitsOptional: false, 32496 clearMaskOnLostFocus: false 32497 },
32498 decimal: { 32499 alias: "numeric" 32500 }, 32501 integer: { 32502 alias: "numeric", 32503 digits: 0, 32504 radixPoint: "" 32505 }, 32506 percentage: { 32507 alias: "numeric", 32508 digits: 2, 32509 digitsOptional: true, 32510 radixPoint: ".", 32511 placeholder: "0", 32512 autoGroup: false, 32513 min: 0, 32514 max: 100, 32515 suffix: " %", 32516 allowMinus: false 32517 } 32518 }); 32519 return Inputmask; 32520 }); 32521}, function(module, exports, __webpack_require__) { 32522 "use strict"; 32523 var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; 32524 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) { 32525 return typeof obj; 32526 } : function(obj) { 32527 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; 32528 }; 32529 (function(factory) { 32530 if (true) { 32531 !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(4), __webpack_require__(2) ], 32532 __WEBPACK_AMD_DEFINE_FACTORY__ = factory, __WEBPACK_AMD_DEFINE_RESULT__ = typeof __WEBPACK_AMD_DEFINE_FACTORY__ === "function" ? __WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__) : __WEBPACK_AMD_DEFINE_FACTORY__, 32533 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 32534 } else {} 32535 })(function($, Inputmask) { 32536 if ($.fn.inputmask === undefined) { 32537 $.fn.inputmask = function(fn, options) { 32538 var nptmask, input = this[0]; 32539 if (options === undefined) options = {}; 32540 if (typeof fn === "string") { 32541 switch (fn) { 32542 case "unmaskedvalue": 32543 return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val(); 32544 32545 case "remove": 32546 return this.each(function() { 32547 if (this.inputmask) this.inputmask.remove(); 32548 }); 32549 32550 case "getemptymask": 32551 return input && input.inputmask ? input.inputmask.getemptymask() : ""; 32552 32553 case "hasMaskedValue": 32554 return input && input.inputmask ? input.inputmask.hasMaskedValue() : false; 32555 32556 case "isComplete": 32557 return input && input.inputmask ? input.inputmask.isComplete() : true; 32558 32559 case "getmetadata": 32560 return input && input.inputmask ? input.inputmask.getmetadata() : undefined; 32561 32562 case "setvalue": 32563 Inputmask.setValue(input, options); 32564 break; 32565 32566 case "option": 32567 if (typeof options === "string") { 32568 if (input && input.inputmask !== undefined) { 32569 return input.inputmask.option(options); 32570 } 32571 } else { 32572 return this.each(function() { 32573 if (this.inputmask !== undefined) { 32574 return this.inputmask.option(options); 32575 } 32576 }); 32577 } 32578 break; 32579 32580 default: 32581 options.alias = fn; 32582 nptmask = new Inputmask(options); 32583 return this.each(function() { 32584 nptmask.mask(this); 32585 }); 32586 } 32587 } else if (Array.isArray(fn)) { 32588 options.alias = fn; 32589 nptmask = new Inputmask(options); 32590 return this.each(function() { 32591 nptmask.mask(this); 32592 }); 32593 } else if ((typeof fn === "undefined" ? "undefined" : _typeof(fn)) == "object") { 32594 nptmask = new Inputmask(fn);
32595 if (fn.mask === undefined && fn.alias === undefined) { 32596 return this.each(function() { 32597 if (this.inputmask !== undefined) { 32598 return this.inputmask.option(fn); 32599 } else nptmask.mask(this); 32600 }); 32601 } else { 32602 return this.each(function() { 32603 nptmask.mask(this); 32604 }); 32605 } 32606 } else if (fn === undefined) { 32607 return this.each(function() { 32608 nptmask = new Inputmask(options); 32609 nptmask.mask(this); 32610 }); 32611 } 32612 }; 32613 } 32614 return $.fn.inputmask; 32615 }); 32616} ]); 32617/*! 32618* inputmask.date.extensions.js 32619* https://github.com/RobinHerbots/Inputmask 32620* Copyright (c) 2010 - 2019 Robin Herbots 32621* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php) 32622* Version: 4.0.8 32623*/ 32624 32625(function(factory) { 32626 if (typeof define === "function" && define.amd) { 32627 define([ "./inputmask" ], factory); 32628 } else if (typeof exports === "object") { 32629 module.exports = factory(require("./inputmask")); 32630 } else { 32631 factory(window.Inputmask); 32632 } 32633})(function(Inputmask) { 32634 var $ = Inputmask.dependencyLib; 32635 var formatCode = { 32636 d: [ "[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", Date.prototype.getDate ], 32637 dd: [ "0[1-9]|[12][0-9]|3[01]", Date.prototype.setDate, "day", function() { 32638 return pad(Date.prototype.getDate.call(this), 2); 32639 } ], 32640 ddd: [ "" ], 32641 dddd: [ "" ], 32642 m: [ "[1-9]|1[012]", Date.prototype.setMonth, "month", function() { 32643 return Date.prototype.getMonth.call(this) + 1; 32644 } ], 32645 mm: [ "0[1-9]|1[012]", Date.prototype.setMonth, "month", function() { 32646 return pad(Date.prototype.getMonth.call(this) + 1, 2); 32647 } ], 32648 mmm: [ "" ], 32649 mmmm: [ "" ], 32650 yy: [ "[0-9]{2}", Date.prototype.setFullYear, "year", function() { 32651 return pad(Date.prototype.getFullYear.call(this), 2); 32652 } ], 32653 yyyy: [ "[0-9]{4}", Date.prototype.setFullYear, "year", function() { 32654 return pad(Date.prototype.getFullYear.call(this), 4); 32655 } ], 32656 h: [ "[1-9]|1[0-2]", Date.prototype.setHours, "hours", Date.prototype.getHours ], 32657 hh: [ "0[1-9]|1[0-2]", Date.prototype.setHours, "hours", function() { 32658 return pad(Date.prototype.getHours.call(this), 2); 32659 } ], 32660 hhh: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ], 32661 H: [ "1?[0-9]|2[0-3]", Date.prototype.setHours, "hours", Date.prototype.getHours ], 32662 HH: [ "0[0-9]|1[0-9]|2[0-3]", Date.prototype.setHours, "hours", function() { 32663 return pad(Date.prototype.getHours.call(this), 2); 32664 } ], 32665 HHH: [ "[0-9]+", Date.prototype.setHours, "hours", Date.prototype.getHours ], 32666 M: [ "[1-5]?[0-9]", Date.prototype.setMinutes, "minutes", Date.prototype.getMinutes ], 32667 MM: [ "0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]", Date.prototype.setMinutes, "minutes", function() { 32668 return pad(Date.prototype.getMinutes.call(this), 2); 32669 } ], 32670 ss: [ "[0-5][0-9]", Date.prototype.setSeconds, "seconds", function() { 32671 return pad(Date.prototype.getSeconds.call(this), 2); 32672 } ], 32673 l: [ "[0-9]{3}", Date.prototype.setMilliseconds, "milliseconds", function() { 32674 return pad(Date.prototype.getMilliseconds.call(this), 3); 32675 } ], 32676 L: [ "[0-9]{2}", Date.prototype.setMilliseconds, "milliseconds", function() { 32677 return pad(Date.prototype.getMilliseconds.call(this), 2); 32678 } ], 32679 t: [ "[ap]" ], 32680 tt: [ "[ap]m" ], 32681 T: [ "[AP]" ], 32682 TT: [ "[AP]M" ], 32683 Z: [ "" ], 32684 o: [ "" ], 32685 S: [ "" ] 32686 }, formatAlias = { 32687 isoDate: "yyyy-mm-dd", 32688 isoTime: "HH:MM:ss", 32689 isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", 32690 isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" 32691 }; 32692 function getTokenizer(opts) { 32693 if (!opts.tokenizer) { 32694 var tokens = []; 32695 for (var ndx in formatCode) { 32696 if (tokens.indexOf(ndx[0]) === -1) tokens.push(ndx[0]); 32697 } 32698 opts.tokenizer = "(" + tokens.join("+|") + ")+?|."; 32699 opts.tokenizer = new RegExp(opts.tokenizer, "g"); 32700 } 32701 return opts.tokenizer; 32702 } 32703 function isValidDate(dateParts, currentResult) { 32704 return !isFinite(dateParts.rawday) || dateParts.day == "29" && !isFinite(dateParts.rawyear) || new Date(dateParts.date.getFullYear(), isFinite(dateParts.rawmonth) ? dateParts.month : dateParts.date.getMonth() + 1, 0).getDate() >= dateParts.day ? currentResult : false;
32705 } 32706 function isDateInRange(dateParts, opts) { 32707 var result = true; 32708 if (opts.min) { 32709 if (dateParts["rawyear"]) { 32710 var rawYear = dateParts["rawyear"].replace(/[^0-9]/g, ""), minYear = opts.min.year.substr(0, rawYear.length); 32711 result = minYear <= rawYear; 32712 } 32713 if (dateParts["year"] === dateParts["rawyear"]) { 32714 if (opts.min.date.getTime() === opts.min.date.getTime()) { 32715 result = opts.min.date.getTime() <= dateParts.date.getTime(); 32716 } 32717 } 32718 } 32719 if (result && opts.max && opts.max.date.getTime() === opts.max.date.getTime()) { 32720 result = opts.max.date.getTime() >= dateParts.date.getTime(); 32721 } 32722 return result; 32723 } 32724 function parse(format, dateObjValue, opts, raw) { 32725 var mask = "", match; 32726 while (match = getTokenizer(opts).exec(format)) { 32727 if (dateObjValue === undefined) { 32728 if (formatCode[match[0]]) { 32729 mask += "(" + formatCode[match[0]][0] + ")"; 32730 } else { 32731 switch (match[0]) { 32732 case "[": 32733 mask += "("; 32734 break; 32735 32736 case "]": 32737 mask += ")?"; 32738 break; 32739 32740 default: 32741 mask += Inputmask.escapeRegex(match[0]); 32742 } 32743 } 32744 } else { 32745 if (formatCode[match[0]]) { 32746 if (raw !== true && formatCode[match[0]][3]) { 32747 var getFn = formatCode[match[0]][3]; 32748 mask += getFn.call(dateObjValue.date); 32749 } else if (formatCode[match[0]][2]) mask += dateObjValue["raw" + formatCode[match[0]][2]]; else mask += match[0]; 32750 } else mask += match[0]; 32751 } 32752 } 32753 return mask; 32754 } 32755 function pad(val, len) { 32756 val = String(val); 32757 len = len || 2; 32758 while (val.length < len) val = "0" + val; 32759 return val; 32760 } 32761 function analyseMask(maskString, format, opts) { 32762 var dateObj = { 32763 date: new Date(1, 0, 1) 32764 }, targetProp, mask = maskString, match, dateOperation, targetValidator; 32765 function extendProperty(value) { 32766 var correctedValue = value.replace(/[^0-9]/g, "0"); 32767 if (correctedValue != value) { 32768 var enteredPart = value.replace(/[^0-9]/g, ""), min = (opts.min && opts.min[targetProp] || value).toString(), max = (opts.max && opts.max[targetProp] || value).toString(); 32769 correctedValue = enteredPart + (enteredPart < min.slice(0, enteredPart.length) ? min.slice(enteredPart.length) : enteredPart > max.slice(0, enteredPart.length) ? max.slice(enteredPart.length) : correctedValue.toString().slice(enteredPart.length)); 32770 } 32771 return correctedValue; 32772 } 32773 function setValue(dateObj, value, opts) { 32774 dateObj[targetProp] = extendProperty(value); 32775 dateObj["raw" + targetProp] = value; 32776 if (dateOperation !== undefined) dateOperation.call(dateObj.date, targetProp == "month" ? parseInt(dateObj[targetProp]) - 1 : dateObj[targetProp]); 32777 } 32778 if (typeof mask === "string") { 32779 while (match = getTokenizer(opts).exec(format)) { 32780 var value = mask.slice(0, match[0].length); 32781 if (formatCode.hasOwnProperty(match[0])) { 32782 targetValidator = formatCode[match[0]][0]; 32783 targetProp = formatCode[match[0]][2]; 32784 dateOperation = formatCode[match[0]][1]; 32785 setValue(dateObj, value, opts); 32786 } 32787 mask = mask.slice(value.length); 32788 } 32789 return dateObj; 32790 } else if (mask && typeof mask === "object" && mask.hasOwnProperty("date")) { 32791 return mask; 32792 } 32793 return undefined; 32794 } 32795 Inputmask.extendAliases({ 32796 datetime: { 32797 mask: function(opts) { 32798 formatCode.S = opts.i18n.ordinalSuffix.join("|"); 32799 opts.inputFormat = formatAlias[opts.inputFormat] || opts.inputFormat; 32800 opts.displayFormat = formatAlias[opts.displayFormat] || opts.displayFormat || opts.inputFormat; 32801 opts.outputFormat = formatAlias[opts.outputFormat] || opts.outputFormat || opts.inputFormat; 32802 opts.placeholder = opts.placeholder !== "" ? opts.placeholder : opts.inputFormat.replace(/[\[\]]/, ""); 32803 opts.regex = parse(opts.inputFormat, undefined, opts); 32804 return null; 32805 }, 32806 placeholder: "", 32807 inputFormat: "isoDateTime", 32808 displayFormat: undefined, 32809 outputFormat: undefined, 32810 min: null, 32811 max: null, 32812 i18n: { 32813 dayNames: [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ], 32814 monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
32814November", "December" ], 32815 ordinalSuffix: [ "st", "nd", "rd", "th" ] 32816 }, 32817 postValidation: function(buffer, pos, currentResult, opts) { 32818 opts.min = analyseMask(opts.min, opts.inputFormat, opts); 32819 opts.max = analyseMask(opts.max, opts.inputFormat, opts); 32820 var result = currentResult, dateParts = analyseMask(buffer.join(""), opts.inputFormat, opts); 32821 if (result && dateParts.date.getTime() === dateParts.date.getTime()) { 32822 result = isValidDate(dateParts, result); 32823 result = result && isDateInRange(dateParts, opts); 32824 } 32825 if (pos && result && currentResult.pos !== pos) { 32826 return { 32827 buffer: parse(opts.inputFormat, dateParts, opts), 32828 refreshFromBuffer: { 32829 start: pos, 32830 end: currentResult.pos 32831 } 32832 }; 32833 } 32834 return result; 32835 }, 32836 onKeyDown: function(e, buffer, caretPos, opts) { 32837 var input = this; 32838 if (e.ctrlKey && e.keyCode === Inputmask.keyCode.RIGHT) { 32839 var today = new Date(), match, date = ""; 32840 while (match = getTokenizer(opts).exec(opts.inputFormat)) { 32841 if (match[0].charAt(0) === "d") { 32842 date += pad(today.getDate(), match[0].length); 32843 } else if (match[0].charAt(0) === "m") { 32844 date += pad(today.getMonth() + 1, match[0].length); 32845 } else if (match[0] === "yyyy") { 32846 date += today.getFullYear().toString(); 32847 } else if (match[0].charAt(0) === "y") { 32848 date += pad(today.getYear(), match[0].length); 32849 } 32850 } 32851 input.inputmask._valueSet(date); 32852 $(input).trigger("setvalue"); 32853 } 32854 }, 32855 onUnMask: function(maskedValue, unmaskedValue, opts) { 32856 return parse(opts.outputFormat, analyseMask(maskedValue, opts.inputFormat, opts), opts, true); 32857 }, 32858 casing: function(elem, test, pos, validPositions) { 32859 if (test.nativeDef.indexOf("[ap]") == 0) return elem.toLowerCase(); 32860 if (test.nativeDef.indexOf("[AP]") == 0) return elem.toUpperCase(); 32861 return elem; 32862 }, 32863 insertMode: false, 32864 shiftPositions: false 32865 } 32866 }); 32867 return Inputmask; 32868}); 32869/*! 32870* inputmask.numeric.extensions.js 32871* https://github.com/RobinHerbots/Inputmask 32872* Copyright (c) 2010 - 2019 Robin Herbots 32873* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php) 32874* Version: 4.0.8 32875*/ 32876 32877(function(factory) { 32878 if (typeof define === "function" && define.amd) { 32879 define([ "./inputmask" ], factory); 32880 } else if (typeof exports === "object") { 32881 module.exports = factory(require("./inputmask")); 32882 } else { 32883 factory(window.Inputmask); 32884 } 32885})(function(Inputmask) { 32886 var $ = Inputmask.dependencyLib; 32887 function autoEscape(txt, opts) { 32888 var escapedTxt = ""; 32889 for (var i = 0; i < txt.length; i++) { 32890 if (Inputmask.prototype.definitions[txt.charAt(i)] || opts.definitions[txt.charAt(i)] || opts.optionalmarker.start === txt.charAt(i) || opts.optionalmarker.end === txt.charAt(i) || opts.quantifiermarker.start === txt.charAt(i) || opts.quantifiermarker.end === txt.charAt(i) || opts.groupmarker.start === txt.charAt(i) || opts.groupmarker.end === txt.charAt(i) || opts.alternatormarker === txt.charAt(i)) { 32891 escapedTxt += "\\" + txt.charAt(i); 32892 } else escapedTxt += txt.charAt(i); 32893 } 32894 return escapedTxt; 32895 } 32896 function alignDigits(buffer, digits, opts) { 32897 if (digits > 0) { 32898 var radixPosition = $.inArray(opts.radixPoint, buffer); 32899 if (radixPosition === -1) { 32900 buffer.push(opts.radixPoint); 32901 radixPosition = buffer.length - 1; 32902 } 32903 for (var i = 1; i <= digits; i++) { 32904 buffer[radixPosition + i] = buffer[radixPosition + i] || "0"; 32905 } 32906 } 32907 return buffer; 32908 } 32909 Inputmask.extendAliases({ 32910 numeric: { 32911 mask: function(opts) { 32912 if (opts.repeat !== 0 && isNaN(opts.integerDigits)) { 32913 opts.integerDigits = opts.repeat; 32914 } 32915 opts.repeat = 0; 32916 if (opts.groupSeparator === opts.radixPoint && opts.digits && opts.digits !== "0") { 32917 if (opts.radixPoint === ".") { 32918 opts.groupSeparator = ","; 32919 } else if (opts.radixPoint === ",") { 32920 opts.groupSeparator = "."; 32921 } else opts.groupSeparator = ""; 32922 } 32923 if (opts.groupSeparator === " ") { 32924 opts.skipOptionalPartCharacter = undefined; 32925 } 32926 opts.autoGroup = opts.autoGroup && opts.groupSeparator !== ""; 32927 if (opts.autoGroup) { 32928 if (typeof opts.groupSize == "string" && isFinite(opts.groupSize)) opts.groupSize = parseInt(opts.groupSize); 32929 if (isFinite(opts.integerDigits)) { 32930 var seps = Math.floor(opts.integerDigits / opts.groupSize); 32931 var mod = opts.integerDigits % opts.groupSize; 32932 opts.integerDigits = parseInt(opts.integerDigits) + (mod === 0 ? seps - 1 : seps); 32933 if (opts.integerDigits < 1) { 32934 opts.integerDigits = "*"; 32935 } 32936 } 32937 } 32938 if (opts.placeholder.length > 1) { 32939 opts.placeholder = opts.placeholder.charAt(0); 32940 } 32941 if (opts.positionCaretOnClick === "radixFocus" && (opts.placeholder === "" && opts.integerOptional === false)) { 32942 opts.positionCaretOnClick = "lvp"; 32943 } 32944 opts.definitions[";"] = opts.definitions["~"]; 32945 opts.definitions[";"].definitionSymbol = "~"; 32946 if (opts.numericInput === true) { 32947 opts.positionCaretOnClick = opts.positionCaretOnClick === "radixFocus" ? "lvp" : opts.positionCaretOnClick; 32948 opts.digitsOptional = false;
32949 if (isNaN(opts.digits)) opts.digits = 2; 32950 opts.decimalProtect = false; 32951 } 32952 var mask = "[+]"; 32953 mask += autoEscape(opts.prefix, opts); 32954 if (opts.integerOptional === true) { 32955 mask += "~{1," + opts.integerDigits + "}"; 32956 } else mask += "~{" + opts.integerDigits + "}"; 32957 if (opts.digits !== undefined) { 32958 var radixDef = opts.decimalProtect ? ":" : opts.radixPoint; 32959 var dq = opts.digits.toString().split(","); 32960 if (isFinite(dq[0]) && dq[1] && isFinite(dq[1])) { 32961 mask += radixDef + ";{" + opts.digits + "}"; 32962 } else if (isNaN(opts.digits) || parseInt(opts.digits) > 0) { 32963 if (opts.digitsOptional) { 32964 mask += "[" + radixDef + ";{1," + opts.digits + "}]"; 32965 } else mask += radixDef + ";{" + opts.digits + "}"; 32966 } 32967 } 32968 mask += autoEscape(opts.suffix, opts); 32969 mask += "[-]"; 32970 opts.greedy = false; 32971 return mask; 32972 }, 32973 placeholder: "", 32974 greedy: false, 32975 digits: "*", 32976 digitsOptional: true, 32977 enforceDigitsOnBlur: false, 32978 radixPoint: ".", 32979 positionCaretOnClick: "radixFocus", 32980 groupSize: 3, 32981 groupSeparator: "", 32982 autoGroup: false, 32983 allowMinus: true, 32984 negationSymbol: { 32985 front: "-", 32986 back: "" 32987 }, 32988 integerDigits: "+", 32989 integerOptional: true, 32990 prefix: "", 32991 suffix: "", 32992 rightAlign: true, 32993 decimalProtect: true, 32994 min: null, 32995 max: null, 32996 step: 1, 32997 insertMode: true, 32998 autoUnmask: false, 32999 unmaskAsNumber: false, 33000 inputType: "text", 33001 inputmode: "numeric", 33002 preValidation: function(buffer, pos, c, isSelection, opts, maskset) { 33003 if (c === "-" || c === opts.negationSymbol.front) { 33004 if (opts.allowMinus !== true) return false; 33005 opts.isNegative = opts.isNegative === undefined ? true : !opts.isNegative; 33006 if (buffer.join("") === "") return true; 33007 return { 33008 caret: maskset.validPositions[pos] ? pos : undefined, 33009 dopost: true 33010 }; 33011 } 33012 if (isSelection === false && c === opts.radixPoint && (opts.digits !== undefined && (isNaN(opts.digits) || parseInt(opts.digits) > 0))) { 33013 var radixPos = $.inArray(opts.radixPoint, buffer); 33014 if (radixPos !== -1 && maskset.validPositions[radixPos] !== undefined) { 33015 if (opts.numericInput === true) { 33016 return pos === radixPos; 33017 } 33018 return { 33019 caret: radixPos + 1 33020 }; 33021 } 33022 } 33023 return true; 33024 }, 33025 postValidation: function(buffer, pos, currentResult, opts) { 33026 function buildPostMask(buffer, opts) { 33027 var postMask = ""; 33028 postMask += "(" + opts.groupSeparator + "*{" + opts.groupSize + "}){*}"; 33029 if (opts.radixPoint !== "") { 33030 var radixSplit = buffer.join("").split(opts.radixPoint); 33031 if (radixSplit[1]) { 33032 postMask += opts.radixPoint + "*{" + radixSplit[1].match(/^\d*\??\d*/)[0].length + "}"; 33033 } 33034 } 33035 return postMask; 33036 } 33037 var suffix = opts.suffix.split(""), prefix = opts.prefix.split(""); 33038 if (currentResult.pos === undefined && currentResult.caret !== undefined && currentResult.dopost !== true) return currentResult; 33039 var caretPos = currentResult.caret !== undefined ? currentResult.caret : currentResult.pos; 33040 var maskedValue = buffer.slice(); 33041 if (opts.numericInput) { 33042 caretPos = maskedValue.length - caretPos - 1; 33043 maskedValue = maskedValue.reverse(); 33044 } 33045 var charAtPos = maskedValue[caretPos]; 33046 if (charAtPos === opts.groupSeparator) { 33047 caretPos += 1; 33048 charAtPos = maskedValue[caretPos]; 33049 } 33050 if (caretPos === maskedValue.length - opts.suffix.length - 1 && charAtPos === opts.radixPoint) return currentResult; 33051 if (charAtPos !== undefined) { 33052 if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) { 33053 maskedValue[caretPos] = "?"; 33054 if (opts.prefix.length > 0 && caretPos >= (opts.isNegative === false ? 1 : 0) && caretPos < opts.prefix.length - 1 + (opts.isNegative === false ? 1 : 0)) { 33055 prefix[caretPos - (opts.isNegative === false ? 1 : 0)] = "?"; 33056 } else if (opts.suffix.length > 0 && caretPos >= maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0)) { 33057 suffix[caretPos - (maskedValue.length - opts.suffix.length - (opts.isNegative === false ? 1 : 0))] = "?"; 33058 } 33059 } 33060 } 33061 prefix = prefix.join(""); 33062 suffix = suffix.join(""); 33063 var processValue = maskedValue.join("").replace(prefix, ""); 33064 processValue = processValue.replace(suffix, ""); 33065 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 33066 processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""); 33067 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 33068 if (isNaN(opts.placeholder)) { 33069 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.placeholder), "g"), ""); 33070 } 33071 if (processValue.length > 1 && processValue.indexOf(opts.radixPoint) !== 1) { 33072 if (charAtPos === "0") { 33073 processValue = processValue.replace(/^\?/g, ""); 33074 } 33075 processValue = processValue.replace(/^0/g, ""); 33076 } 33077 if (processValue.charAt(0) === opts.radixPoint && opts.radixPoint !== "" && opts.numericInput !== true) { 33078 processValue = "0" + processValue; 33079 } 33080 if (processValue !== "") { 33081 processValue = processValue.split(""); 33082 if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && isFinite(opts.digits)) { 33083 var radixPosition = $.inArray(opts.radixPoint, processValue); 33084 var rpb = $.inArray(opts.radixPoint, maskedValue); 33085 if (radixPosition === -1) { 33086 processValue.push(opts.radixPoint); 33087 radixPosition = processValue.length - 1; 33088 } 33089 for (var i = 1; i <= opts.digits; i++) { 33090 if ((!opts.digitsOptional || opts.enforceDigitsOnBlur && currentResult.event === "blur") && (processValue[radixPosition + i] === undefined || processValue[radixPosition + i] === opts.placeholder.charAt(0))) { 33091 processValue[radixPosition + i] = currentResult.placeholder || opts.placeholder.charAt(0); 33092 } else if (rpb !== -1 && maskedValue[rpb + i] !== undefined) { 33093 processValue[radixPosition + i] = processValue[radixPosition + i] || maskedValue[rpb + i]; 33094 } 33095 } 33096 } 33097 if (opts.autoGroup === true && opts.groupSeparator !== "" && (charAtPos !== opts.radixPoint || currentResult.pos !== undefined || currentResult.dopost)) { 33098 var addRadix = processValue[processValue.length - 1] === opts.radixPoint && currentResult.c === opts.radixPoint; 33099 processValue = Inputmask(buildPostMask(processValue, opts), { 33100 numericInput: true, 33101 jitMasking: true, 33102 definitions: { 33103 "*": { 33104 validator: "[0-9?]", 33105 cardinality: 1 33106 } 33107 } 33108 }).format(processValue.join("")); 33109 if (addRadix) processValue += opts.radixPoint; 33110 if (processValue.charAt(0) === opts.groupSeparator) { 33111 processValue.substr(1); 33112 } 33113 } else processValue = processValue.join(""); 33114 } 33115 if (opts.isNegative && currentResult.event === "blur") { 33116 opts.isNegative = processValue !== "0"; 33117 } 33118 processValue = prefix + processValue; 33119 processValue += suffix; 33120 if (opts.isNegative) { 33121 processValue = opts.negationSymbol.front + processValue; 33122 processValue += opts.negationSymbol.back; 33123 } 33124 processValue = processValue.split(""); 33125 if (charAtPos !== undefined) { 33126 if (charAtPos !== opts.radixPoint && charAtPos !== opts.negationSymbol.front && charAtPos !== opts.negationSymbol.back) { 33127 caretPos = $.inArray("?", processValue); 33128 if (caretPos > -1) { 33129 processValue[caretPos] = charAtPos; 33130 } else caretPos = currentResult.caret || 0; 33131 } else if (charAtPos === opts.radixPoint || charAtPos === opts.negationSymbol.front || charAtPos === opts.negationSymbol.back) { 33132 var newCaretPos = $.inArray(charAtPos, processValue); 33133 if (newCaretPos !== -1) caretPos = newCaretPos; 33134 } 33135 } 33136 if (opts.numericInput) { 33137 caretPos = processValue.length - caretPos - 1; 33138 processValue = processValue.reverse(); 33139 } 33140 var rslt = { 33141 caret: (charAtPos === undefined || currentResult.pos !== undefined) && caretPos !== undefined ? caretPos + (opts.numericInput ? -1 : 1) : caretPos, 33142 buffer: processValue, 33143 refreshFromBuffer: currentResult.dopost || buffer.join("") !== processValue.join("") 33144 }; 33145 return rslt.refreshFromBuffer ? rslt : currentResult; 33146 }, 33147 onBeforeWrite: function(e, buffer, caretPos, opts) { 33148 function parseMinMaxOptions(opts) { 33149 if (opts.parseMinMaxOptions === undefined) { 33150 if (opts.min !== null) { 33151 opts.min = opts.min.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 33152 if (opts.radixPoint === ",") opts.min = opts.min.replace(opts.radixPoint, "."); 33153 opts.min = isFinite(opts.min) ? parseFloat(opts.min) : NaN; 33154 if (isNaN(opts.min)) opts.min = Number.MIN_VALUE; 33155 } 33156 if (opts.max !== null) { 33157 opts.max = opts.max.toString().replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 33158 if (opts.radixPoint === ",") opts.max = opts.max.replace(opts.radixPoint, "."); 33159 opts.max = isFinite(opts.max) ? parseFloat(opts.max) : NaN; 33160 if (isNaN(opts.max)) opts.max = Number.MAX_VALUE; 33161 } 33162 opts.parseMinMaxOptions = "done"; 33163 } 33164 } 33165 if (e) { 33166 switch (e.type) { 33167 case "keydown": 33168 return opts.postValidation(buffer, caretPos, { 33169 caret: caretPos, 33170 dopost: true 33171 }, opts); 33172 33173 case "blur": 33174 case "checkval": 33175 var unmasked; 33176 parseMinMaxOptions(opts); 33177 if (opts.min !== null || opts.max !== null) { 33178 unmasked = opts.onUnMask(buffer.join(""), undefined, $.extend({}, opts, { 33179 unmaskAsNumber: true 33180 })); 33181 if (opts.min !== null && unmasked < opts.min) { 33182 opts.isNegative = opts.min < 0; 33183 return opts.postValidation(opts.min.toString().replace(".", opts.radixPoint).split(""), caretPos, { 33184 caret: caretPos, 33185 dopost: true, 33186 placeholder: "0" 33187 }, opts); 33188 } else if (opts.max !== null && unmasked > opts.max) { 33189 opts.isNegative = opts.max < 0; 33190 return opts.postValidation(opts.max.toString().replace(".", opts.radixPoint).split(""), caretPos, { 33191 caret: caretPos, 33192 dopost: true, 33193 placeholder: "0" 33194 }, opts); 33195 } 33196 } 33197 return opts.postValidation(buffer, caretPos, { 33198 caret: caretPos, 33199 placeholder: "0", 33200 event: "blur" 33201 }, opts); 33202 33203 case "_checkval": 33204 return { 33205 caret: caretPos 33206 }; 33207 33208 default: 33209 break; 33210 } 33211 } 33212 }, 33213 regex: { 33214 integerPart: function(opts, emptyCheck) { 33215 return emptyCheck ? new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?") : new RegExp("[" + Inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+"); 33216 }, 33217 integerNPart: function(opts) { 33218 return new RegExp("[\\d" + Inputmask.escapeRegex(opts.groupSeparator) + Inputmask.escapeRegex(opts.placeholder.charAt(0)) + "]+"); 33219 } 33220 }, 33221 definitions: { 33222 "~": { 33223 validator: function(chrs, maskset, pos, strict, opts, isSelection) { 33224 var isValid, l; 33225 if (chrs === "k" || chrs === "m") { 33226 isValid = { 33227 insert: [], 33228 c: 0 33229 }; 33230 for (var i = 0, l = chrs === "k" ? 2 : 5; i < l; i++) { 33231 isValid.insert.push({ 33232 pos: pos + i, 33233 c: 0 33234 }); 33235 } 33236 isValid.pos = pos + l; 33237 return isValid; 33238 } 33239 isValid = strict ? new RegExp("[0-9" + Inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs); 33240 if (isValid === true) { 33241
33241 if (opts.numericInput !== true && maskset.validPositions[pos] !== undefined && maskset.validPositions[pos].match.def === "~" && !isSelection) { 33242 var processValue = maskset.buffer.join(""); 33243 processValue = processValue.replace(new RegExp("[-" + Inputmask.escapeRegex(opts.negationSymbol.front) + "]", "g"), ""); 33244 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 33245 var pvRadixSplit = processValue.split(opts.radixPoint); 33246 if (pvRadixSplit.length > 1) { 33247 pvRadixSplit[1] = pvRadixSplit[1].replace(/0/g, opts.placeholder.charAt(0)); 33248 } 33249 if (pvRadixSplit[0] === "0") { 33250 pvRadixSplit[0] = pvRadixSplit[0].replace(/0/g, opts.placeholder.charAt(0)); 33251 } 33252 processValue = pvRadixSplit[0] + opts.radixPoint + pvRadixSplit[1] || ""; 33253 var bufferTemplate = maskset._buffer.join(""); 33254 if (processValue === opts.radixPoint) { 33255 processValue = bufferTemplate; 33256 } 33257 while (processValue.match(Inputmask.escapeRegex(bufferTemplate) + "$") === null) { 33258 bufferTemplate = bufferTemplate.slice(1); 33259 } 33260 processValue = processValue.replace(bufferTemplate, ""); 33261 processValue = processValue.split(""); 33262 if (processValue[pos] === undefined) { 33263 isValid = { 33264 pos: pos, 33265 remove: pos 33266 }; 33267 } else { 33268 isValid = { 33269 pos: pos 33270 }; 33271 } 33272 } 33273 } else if (!strict && chrs === opts.radixPoint && maskset.validPositions[pos - 1] === undefined) { 33274 isValid = { 33275 insert: { 33276 pos: pos, 33277 c: 0 33278 }, 33279 pos: pos + 1 33280 }; 33281 } 33282 return isValid; 33283 }, 33284 cardinality: 1 33285 }, 33286 "+": { 33287 validator: function(chrs, maskset, pos, strict, opts) { 33288 return opts.allowMinus && (chrs === "-" || chrs === opts.negationSymbol.front); 33289 }, 33290 cardinality: 1, 33291 placeholder: "" 33292 }, 33293 "-": { 33294 validator: function(chrs, maskset, pos, strict, opts) { 33295 return opts.allowMinus && chrs === opts.negationSymbol.back; 33296 }, 33297 cardinality: 1, 33298 placeholder: "" 33299 }, 33300 ":": { 33301 validator: function(chrs, maskset, pos, strict, opts) { 33302 var radix = "[" + Inputmask.escapeRegex(opts.radixPoint) + "]"; 33303 var isValid = new RegExp(radix).test(chrs); 33304 if (isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder === opts.radixPoint) { 33305 isValid = { 33306 caret: pos + 1 33307 }; 33308 } 33309 return isValid; 33310 }, 33311 cardinality: 1, 33312 placeholder: function(opts) { 33313 return opts.radixPoint; 33314 } 33315 } 33316 }, 33317 onUnMask: function(maskedValue, unmaskedValue, opts) { 33318 if (unmaskedValue === "" && opts.nullable === true) { 33319 return unmaskedValue; 33320 } 33321 var processValue = maskedValue.replace(opts.prefix, ""); 33322 processValue = processValue.replace(opts.suffix, ""); 33323 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator), "g"), ""); 33324 if (opts.placeholder.charAt(0) !== "") { 33325 processValue = processValue.replace(new RegExp(opts.placeholder.charAt(0), "g"), "0"); 33326 } 33327 if (opts.unmaskAsNumber) { 33328 if (opts.radixPoint !== "" && processValue.indexOf(opts.radixPoint) !== -1) processValue = processValue.replace(Inputmask.escapeRegex.call(this, opts.radixPoint), "."); 33329 processValue = processValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"); 33330 processValue = processValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 33331 return Number(processValue); 33332 } 33333 return processValue; 33334 }, 33335 isComplete: function(buffer, opts) { 33336 var maskedValue = (opts.numericInput ? buffer.slice().reverse() : buffer).join(""); 33337 maskedValue = maskedValue.replace(new RegExp("^" + Inputmask.escapeRegex(opts.negationSymbol.front)), "-"); 33338 maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""); 33339 maskedValue = maskedValue.replace(opts.prefix, ""); 33340 maskedValue = maskedValue.replace(opts.suffix, ""); 33341 maskedValue = maskedValue.replace(new RegExp(Inputmask.escapeRegex(opts.groupSeparator) + "([0-9]{3})", "g"), "$1"); 33342 if (opts.radixPoint === ",") maskedValue = maskedValue.replace(Inputmask.escapeRegex(opts.radixPoint), "."); 33343 return isFinite(maskedValue); 33344 }, 33345 onBeforeMask: function(initialValue, opts) { 33346 opts.isNegative = undefined; 33347 var radixPoint = opts.radixPoint || ","; 33348 if ((typeof initialValue == "number" || opts.inputType === "number") && radixPoint !== "") { 33349 initialValue = initialValue.toString().replace(".", radixPoint); 33350 } 33351 var valueParts = initialValue.split(radixPoint), integerPart = valueParts[0].replace(/[^\-0-9]/g, ""), decimalPart = valueParts.length > 1 ? valueParts[1].replace(/[^0-9]/g, "") : ""; 33352 initialValue = integerPart + (decimalPart !== "" ? radixPoint + decimalPart : decimalPart); 33353 var digits = 0; 33354 if (radixPoint !== "") { 33355 digits = decimalPart.length; 33356 if (decimalPart !== "") { 33357 var digitsFactor = Math.pow(10, digits || 1); 33358 if (isFinite(opts.digits)) { 33359 digits = parseInt(opts.digits); 33360 digitsFactor = Math.pow(10, digits); 33361 } 33362 initialValue = initialValue.replace(Inputmask.escapeRegex(radixPoint), "."); 33363 if (isFinite(initialValue)) initialValue = Math.round(parseFloat(initialValue) * digitsFactor) / digitsFactor; 33364 initialValue = initialValue.toString().replace(".", radixPoint); 33365 } 33366 } 33367 if (opts.digits === 0 && initialValue.indexOf(Inputmask.escapeRegex(radixPoint)) !== -1) { 33368 initialValue = initialValue.substring(0, initialValue.indexOf(Inputmask.escapeRegex(radixPoint))); 33369 } 33370 return alignDigits(initialValue.toString().split(""), digits, opts).join(""); 33371 }, 33372 onKeyDown: function(e, buffer, caretPos, opts) { 33373 var $input = $(this); 33374 if (e.ctrlKey) { 33375 switch (e.keyCode) { 33376 case Inputmask.keyCode.UP: 33377 $input.val(parseFloat(this.inputmask.unmaskedvalue()) + parseInt(opts.step)); 33378 $input.trigger("setvalue"); 33379 break; 33380 33381 case Inputmask.keyCode.DOWN: 33382 $input.val(parseFloat(this.inputmask.unmaskedvalue()) - parseInt(opts.step)); 33383 $input.trigger("setvalue"); 33384 break; 33385 } 33386 } 33387 } 33388 }, 33389 currency: { 33390 prefix: "$ ", 33391 groupSeparator: ",", 33392 alias: "numeric", 33393 placeholder: "0", 33394 autoGroup: true, 33395 digits: 2, 33396 digitsOptional: false, 33397 clearMaskOnLostFocus: false 33398 },
vendor: 9,815 bytes, lines 33399-33733
33399 decimal: { 33400 alias: "numeric" 33401 }, 33402 integer: { 33403 alias: "numeric", 33404 digits: 0, 33405 radixPoint: "" 33406 }, 33407 percentage: { 33408 alias: "numeric", 33409 digits: 2, 33410 digitsOptional: true, 33411 radixPoint: ".", 33412 placeholder: "0", 33413 autoGroup: false, 33414 min: 0, 33415 max: 100, 33416 suffix: " %", 33417 allowMinus: false 33418 } 33419 }); 33420 return Inputmask; 33421}); 33422/*! nouislider - 12.1.0 - 10/25/2018 */ 33423(function(factory) { 33424 if (typeof define === "function" && define.amd) { 33425 // AMD. Register as an anonymous module. 33426 define([], factory); 33427 } else if (typeof exports === "object") { 33428 // Node/CommonJS 33429 module.exports = factory(); 33430 } else { 33431 // Browser globals 33432 window.noUiSlider = factory(); 33433 } 33434})(function() { 33435 "use strict"; 33436 33437 var VERSION = "12.1.0"; 33438 33439 function isValidFormatter(entry) { 33440 return typeof entry === "object" && typeof entry.to === "function" && typeof entry.from === "function"; 33441 } 33442 33443 function removeElement(el) { 33444 el.parentElement.removeChild(el); 33445 } 33446 33447 function isSet(value) { 33448 return value !== null && value !== undefined; 33449 } 33450 33451 // Bindable version 33452 function preventDefault(e) { 33453 e.preventDefault(); 33454 } 33455 33456 // Removes duplicates from an array. 33457 function unique(array) { 33458 return array.filter(function(a) { 33459 return !this[a] ? (this[a] = true) : false; 33460 }, {}); 33461 } 33462 33463 // Round a value to the closest 'to'. 33464 function closest(value, to) { 33465 return Math.round(value / to) * to; 33466 } 33467 33468 // Current position of an element relative to the document. 33469 function offset(elem, orientation) { 33470 var rect = elem.getBoundingClientRect(); 33471 var doc = elem.ownerDocument; 33472 var docElem = doc.documentElement; 33473 var pageOffset = getPageOffset(doc); 33474 33475 // getBoundingClientRect contains left scroll in Chrome on Android. 33476 // I haven't found a feature detection that proves this. Worst case 33477 // scenario on mis-match: the 'tap' feature on horizontal sliders breaks. 33478 if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) { 33479 pageOffset.x = 0; 33480 } 33481 33482 return orientation 33483 ? rect.top + pageOffset.y - docElem.clientTop 33484 : rect.left + pageOffset.x - docElem.clientLeft; 33485 } 33486 33487 // Checks whether a value is numerical. 33488 function isNumeric(a) { 33489 return typeof a === "number" && !isNaN(a) && isFinite(a); 33490 } 33491 33492 // Sets a class and removes it after [duration] ms. 33493 function addClassFor(element, className, duration) { 33494 if (duration > 0) { 33495 addClass(element, className); 33496 setTimeout(function() { 33497 removeClass(element, className); 33498 }, duration); 33499 } 33500 } 33501 33502 // Limits a value to 0 - 100 33503 function limit(a) { 33504 return Math.max(Math.min(a, 100), 0); 33505 } 33506 33507 // Wraps a variable as an array, if it isn't one yet. 33508 // Note that an input array is returned by reference! 33509 function asArray(a) { 33510 return Array.isArray(a) ? a : [a]; 33511 } 33512 33513 // Counts decimals 33514 function countDecimals(numStr) { 33515 numStr = String(numStr); 33516 var pieces = numStr.split("."); 33517 return pieces.length > 1 ? pieces[1].length : 0; 33518 } 33519 33520 // http://youmightnotneedjquery.com/#add_class 33521 function addClass(el, className) { 33522 if (el.classList) { 33523 el.classList.add(className); 33524 } else { 33525 el.className += " " + className; 33526 } 33527 } 33528 33529 // http://youmightnotneedjquery.com/#remove_class 33530 function removeClass(el, className) { 33531 if (el.classList) { 33532 el.classList.remove(className); 33533 } else { 33534 el.className = el.className.replace( 33535 new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"), 33536 " " 33537 ); 33538 } 33539 } 33540 33541 // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/ 33542 function hasClass(el, className) { 33543 return el.classList 33544 ? el.classList.contains(className) 33545 : new RegExp("\\b" + className + "\\b").test(el.className); 33546 } 33547 33548 // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes 33549 function getPageOffset(doc) { 33550 var supportPageOffset = window.pageXOffset !== undefined; 33551 var isCSS1Compat = (doc.compatMode || "") === "CSS1Compat"; 33552 var x = supportPageOffset 33553 ? window.pageXOffset 33554 : isCSS1Compat 33555 ? doc.documentElement.scrollLeft 33556 : doc.body.scrollLeft; 33557 var y = supportPageOffset 33558 ? window.pageYOffset 33559 : isCSS1Compat 33560 ? doc.documentElement.scrollTop 33561 : doc.body.scrollTop; 33562 33563 return { 33564 x: x, 33565 y: y 33566 }; 33567 } 33568 33569 // we provide a function to compute constants instead 33570 // of accessing window.* as soon as the module needs it 33571 // so that we do not compute anything if not needed 33572 function getActions() { 33573 // Determine the events to bind. IE11 implements pointerEvents without 33574 // a prefix, which breaks compatibility with the IE10 implementation. 33575 return window.navigator.pointerEnabled 33576 ? { 33577 start: "pointerdown", 33578 move: "pointermove", 33579 end: "pointerup" 33580 } 33581 : window.navigator.msPointerEnabled 33582 ? { 33583 start: "MSPointerDown", 33584 move: "MSPointerMove", 33585 end: "MSPointerUp" 33586 } 33587 : { 33588 start: "mousedown touchstart", 33589 move: "mousemove touchmove", 33590 end: "mouseup touchend" 33591 }; 33592 } 33593 33594 // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md 33595 // Issue #785 33596 function getSupportsPassive() { 33597 var supportsPassive = false; 33598 33599 /* eslint-disable */ 33600 try { 33601 var opts = Object.defineProperty({}, "passive", { 33602 get: function() { 33603 supportsPassive = true; 33604 } 33605 }); 33606 33607 window.addEventListener("test", null, opts); 33608 } catch (e) {} 33609 /* eslint-enable */ 33610 33611 return supportsPassive; 33612 } 33613 33614 function getSupportsTouchActionNone() { 33615 return window.CSS && CSS.supports && CSS.supports("touch-action", "none"); 33616 } 33617 33618 // Value calculation 33619 33620 // Determine the size of a sub-range in relation to a full range. 33621 function subRangeRatio(pa, pb) { 33622 return 100 / (pb - pa); 33623 } 33624 33625 // (percentage) How many percent is this value of this range? 33626 function fromPercentage(range, value) { 33627 return (value * 100) / (range[1] - range[0]); 33628 } 33629 33630 // (percentage) Where is this value on this range? 33631 function toPercentage(range, value) { 33632 return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0]); 33633 } 33634 33635 // (value) How much is this percentage on this range? 33636 function isPercentage(range, value) { 33637 return (value * (range[1] - range[0])) / 100 + range[0]; 33638 } 33639 33640 // Range conversion 33641 33642 function getJ(value, arr) { 33643 var j = 1; 33644 33645 while (value >= arr[j]) { 33646 j += 1; 33647 } 33648 33649 return j; 33650 } 33651 33652 // (percentage) Input a value, find where, on a scale of 0-100, it applies. 33653 function toStepping(xVal, xPct, value) { 33654 if (value >= xVal.slice(-1)[0]) { 33655 return 100; 33656 } 33657 33658 var j = getJ(value, xVal); 33659 var va = xVal[j - 1]; 33660 var vb = xVal[j]; 33661 var pa = xPct[j - 1]; 33662 var pb = xPct[j]; 33663 33664 return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb); 33665 } 33666 33667 // (value) Input a percentage, find where it is on the specified range. 33668 function fromStepping(xVal, xPct, value) { 33669 // There is no range group that fits 100 33670 if (value >= 100) { 33671 return xVal.slice(-1)[0]; 33672 } 33673 33674 var j = getJ(value, xPct); 33675 var va = xVal[j - 1]; 33676 var vb = xVal[j]; 33677 var pa = xPct[j - 1]; 33678 var pb = xPct[j]; 33679 33680 return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb)); 33681 } 33682 33683 // (percentage) Get the step that applies at a certain value. 33684 function getStep(xPct, xSteps, snap, value) { 33685 if (value === 100) { 33686 return value; 33687 } 33688 33689 var j = getJ(value, xPct); 33690 var a = xPct[j - 1]; 33691 var b = xPct[j]; 33692 33693 // If 'snap' is set, steps are used as fixed points on the slider. 33694 if (snap) { 33695 // Find the closest position, a or b. 33696 if (value - a > (b - a) / 2) { 33697 return b; 33698 } 33699 33700 return a; 33701 } 33702 33703 if (!xSteps[j - 1]) { 33704 return value; 33705 } 33706 33707 return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]); 33708 } 33709 33710 // Entry parsing 33711 33712 function handleEntryPoint(index, value, that) { 33713 var percentage; 33714 33715 // Wrap numerical input in an array. 33716 if (typeof value === "number") { 33717 value = [value]; 33718 } 33719 33720 // Reject any invalid input, by testing whether value is an array. 33721 if (!Array.isArray(value)) { 33722 throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value."); 33723 } 33724 33725 // Covert min/max syntax to 0 and 100. 33726 if (index === "min") { 33727 percentage = 0; 33728 } else if (index === "max") { 33729 percentage = 100; 33730 } else { 33731 percentage = parseFloat(index); 33732 } 33733
33734 // Check for correct input. 33735 if (!isNumeric(percentage) || !isNumeric(value[0])) { 33736 throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric."); 33737 } 33738 33739 // Store values. 33740 that.xPct.push(percentage); 33741 that.xVal.push(value[0]); 33742 33743 // NaN will evaluate to false too, but to keep 33744 // logging clear, set step explicitly. Make sure 33745 // not to override the 'step' setting with false. 33746 if (!percentage) { 33747 if (!isNaN(value[1])) { 33748 that.xSteps[0] = value[1]; 33749 } 33750 } else { 33751 that.xSteps.push(isNaN(value[1]) ? false : value[1]); 33752 } 33753 33754 that.xHighestCompleteStep.push(0); 33755 } 33756 33757 function handleStepPoint(i, n, that) { 33758 // Ignore 'false' stepping. 33759 if (!n) { 33760 return true; 33761 } 33762 33763 // Factor to range ratio 33764 that.xSteps[i] = 33765 fromPercentage([that.xVal[i], that.xVal[i + 1]], n) / subRangeRatio(that.xPct[i], that.xPct[i + 1]); 33766 33767 var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i]; 33768 var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1); 33769 var step = that.xVal[i] + that.xNumSteps[i] * highestStep; 33770 33771 that.xHighestCompleteStep[i] = step; 33772 } 33773 33774 // Interface 33775 33776 function Spectrum(entry, snap, singleStep) { 33777 this.xPct = []; 33778 this.xVal = []; 33779 this.xSteps = [singleStep || false]; 33780 this.xNumSteps = [false]; 33781 this.xHighestCompleteStep = []; 33782 33783 this.snap = snap; 33784 33785 var index; 33786 var ordered = []; // [0, 'min'], [1, '50%'], [2, 'max'] 33787 33788 // Map the object keys to an array. 33789 for (index in entry) { 33790 if (entry.hasOwnProperty(index)) { 33791 ordered.push([entry[index], index]); 33792 } 33793 } 33794 33795 // Sort all entries by value (numeric sort). 33796 if (ordered.length && typeof ordered[0][0] === "object") { 33797 ordered.sort(function(a, b) { 33798 return a[0][0] - b[0][0]; 33799 }); 33800 } else { 33801 ordered.sort(function(a, b) { 33802 return a[0] - b[0]; 33803 }); 33804 } 33805 33806 // Convert all entries to subranges. 33807 for (index = 0; index < ordered.length; index++) { 33808 handleEntryPoint(ordered[index][1], ordered[index][0], this); 33809 } 33810 33811 // Store the actual step values. 33812 // xSteps is sorted in the same order as xPct and xVal. 33813 this.xNumSteps = this.xSteps.slice(0); 33814 33815 // Convert all numeric steps to the percentage of the subrange they represent. 33816 for (index = 0; index < this.xNumSteps.length; index++) { 33817 handleStepPoint(index, this.xNumSteps[index], this); 33818 } 33819 } 33820 33821 Spectrum.prototype.getMargin = function(value) { 33822 var step = this.xNumSteps[0]; 33823 33824 if (step && (value / step) % 1 !== 0) { 33825 throw new Error("noUiSlider (" + VERSION + "): 'limit', 'margin' and 'padding' must be divisible by step."); 33826 } 33827 33828 return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false; 33829 }; 33830 33831 Spectrum.prototype.toStepping = function(value) { 33832 value = toStepping(this.xVal, this.xPct, value); 33833 33834 return value; 33835 }; 33836 33837 Spectrum.prototype.fromStepping = function(value) { 33838 return fromStepping(this.xVal, this.xPct, value); 33839 }; 33840 33841 Spectrum.prototype.getStep = function(value) { 33842 value = getStep(this.xPct, this.xSteps, this.snap, value); 33843 33844 return value; 33845 }; 33846 33847 Spectrum.prototype.getNearbySteps = function(value) { 33848 var j = getJ(value, this.xPct); 33849 33850 return { 33851 stepBefore: { 33852 startValue: this.xVal[j - 2], 33853 step: this.xNumSteps[j - 2], 33854 highestStep: this.xHighestCompleteStep[j - 2] 33855 }, 33856 thisStep: { 33857 startValue: this.xVal[j - 1], 33858 step: this.xNumSteps[j - 1], 33859 highestStep: this.xHighestCompleteStep[j - 1] 33860 }, 33861 stepAfter: { 33862 startValue: this.xVal[j], 33863 step: this.xNumSteps[j],
33864 highestStep: this.xHighestCompleteStep[j] 33865 } 33866 }; 33867 }; 33868 33869 Spectrum.prototype.countStepDecimals = function() { 33870 var stepDecimals = this.xNumSteps.map(countDecimals); 33871 return Math.max.apply(null, stepDecimals); 33872 }; 33873 33874 // Outside testing 33875 Spectrum.prototype.convert = function(value) { 33876 return this.getStep(this.toStepping(value)); 33877 }; 33878 33879 /* Every input option is tested and parsed. This'll prevent 33880 endless validation in internal methods. These tests are 33881 structured with an item for every option available. An 33882 option can be marked as required by setting the 'r' flag. 33883 The testing function is provided with three arguments: 33884 - The provided value for the option; 33885 - A reference to the options object; 33886 - The name for the option; 33887 33888 The testing function returns false when an error is detected, 33889 or true when everything is OK. It can also modify the option 33890 object, to make sure all values can be correctly looped elsewhere. */ 33891 33892 var defaultFormatter = { 33893 to: function(value) { 33894 return value !== undefined && value.toFixed(2); 33895 }, 33896 from: Number 33897 }; 33898 33899 function validateFormat(entry) { 33900 // Any object with a to and from method is supported. 33901 if (isValidFormatter(entry)) { 33902 return true; 33903 } 33904 33905 throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods."); 33906 } 33907 33908 function testStep(parsed, entry) { 33909 if (!isNumeric(entry)) { 33910 throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric."); 33911 } 33912 33913 // The step option can still be used to set stepping 33914 // for linear sliders. Overwritten if set in 'range'. 33915 parsed.singleStep = entry; 33916 } 33917 33918 function testRange(parsed, entry) { 33919 // Filter incorrect input. 33920 if (typeof entry !== "object" || Array.isArray(entry)) { 33921 throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object."); 33922 } 33923 33924 // Catch missing start or end. 33925 if (entry.min === undefined || entry.max === undefined) { 33926 throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'."); 33927 } 33928 33929 // Catch equal start or end. 33930 if (entry.min === entry.max) { 33931 throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal."); 33932 } 33933 33934 parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep); 33935 } 33936 33937 function testStart(parsed, entry) { 33938 entry = asArray(entry); 33939 33940 // Validate input. Values aren't tested, as the public .val method 33941 // will always provide a valid location. 33942 if (!Array.isArray(entry) || !entry.length) { 33943 throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect."); 33944 } 33945 33946 // Store the number of handles. 33947 parsed.handles = entry.length; 33948 33949 // When the slider is initialized, the .val method will 33950 // be called with the start options. 33951 parsed.start = entry; 33952 } 33953 33954 function testSnap(parsed, entry) { 33955 // Enforce 100% stepping within subranges. 33956 parsed.snap = entry; 33957 33958 if (typeof entry !== "boolean") { 33959 throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean."); 33960 } 33961 } 33962 33963 function testAnimate(parsed, entry) { 33964 // Enforce 100% stepping within subranges. 33965 parsed.animate = entry; 33966 33967 if (typeof entry !== "boolean") { 33968 throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean."); 33969 } 33970 } 33971 33972 function testAnimationDuration(parsed, entry) { 33973 parsed.animationDuration = entry; 33974 33975 if (typeof entry !== "number") { 33976 throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number."); 33977 } 33978 } 33979 33980 function testConnect(parsed, entry) { 33981 var connect = [false]; 33982 var i; 33983 33984 // Map legacy options 33985 if (entry === "lower") { 33986 entry = [true, false]; 33987 } else if (entry === "upper") {
33988 entry = [false, true]; 33989 } 33990 33991 // Handle boolean options 33992 if (entry === true || entry === false) { 33993 for (i = 1; i < parsed.handles; i++) { 33994 connect.push(entry); 33995 } 33996 33997 connect.push(false); 33998 } 33999 34000 // Reject invalid input 34001 else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) { 34002 throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count."); 34003 } else { 34004 connect = entry; 34005 } 34006 34007 parsed.connect = connect; 34008 } 34009 34010 function testOrientation(parsed, entry) { 34011 // Set orientation to an a numerical value for easy 34012 // array selection. 34013 switch (entry) { 34014 case "horizontal": 34015 parsed.ort = 0; 34016 break; 34017 case "vertical": 34018 parsed.ort = 1; 34019 break; 34020 default: 34021 throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid."); 34022 } 34023 } 34024 34025 function testMargin(parsed, entry) { 34026 if (!isNumeric(entry)) { 34027 throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric."); 34028 } 34029 34030 // Issue #582 34031 if (entry === 0) { 34032 return; 34033 } 34034 34035 parsed.margin = parsed.spectrum.getMargin(entry); 34036 34037 if (!parsed.margin) { 34038 throw new Error("noUiSlider (" + VERSION + "): 'margin' option is only supported on linear sliders."); 34039 } 34040 } 34041 34042 function testLimit(parsed, entry) { 34043 if (!isNumeric(entry)) { 34044 throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric."); 34045 } 34046 34047 parsed.limit = parsed.spectrum.getMargin(entry); 34048 34049 if (!parsed.limit || parsed.handles < 2) { 34050 throw new Error( 34051 "noUiSlider (" + 34052 VERSION + 34053 "): 'limit' option is only supported on linear sliders with 2 or more handles." 34054 ); 34055 } 34056 } 34057 34058 function testPadding(parsed, entry) { 34059 if (!isNumeric(entry) && !Array.isArray(entry)) { 34060 throw new Error( 34061 "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers." 34062 ); 34063 } 34064 34065 if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) { 34066 throw new Error( 34067 "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers." 34068 ); 34069 } 34070 34071 if (entry === 0) { 34072 return; 34073 } 34074 34075 if (!Array.isArray(entry)) { 34076 entry = [entry, entry]; 34077 } 34078 34079 // 'getMargin' returns false for invalid values. 34080 parsed.padding = [parsed.spectrum.getMargin(entry[0]), parsed.spectrum.getMargin(entry[1])]; 34081 34082 if (parsed.padding[0] === false || parsed.padding[1] === false) { 34083 throw new Error("noUiSlider (" + VERSION + "): 'padding' option is only supported on linear sliders."); 34084 } 34085 34086 if (parsed.padding[0] < 0 || parsed.padding[1] < 0) { 34087 throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s)."); 34088 } 34089 34090 if (parsed.padding[0] + parsed.padding[1] >= 100) { 34091 throw new Error("noUiSlider (" + VERSION + "): 'padding' option must not exceed 100% of the range."); 34092 } 34093 } 34094 34095 function testDirection(parsed, entry) { 34096 // Set direction as a numerical value for easy parsing. 34097 // Invert connection for RTL sliders, so that the proper 34098 // handles get the connect/background classes. 34099 switch (entry) { 34100 case "ltr": 34101 parsed.dir = 0; 34102 break; 34103 case "rtl": 34104 parsed.dir = 1; 34105 break; 34106 default: 34107 throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized."); 34108 } 34109 } 34110 34111 function testBehaviour(parsed, entry) { 34112 // Make sure the input is a string. 34113 if (typeof entry !== "string") { 34114 throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options."); 34115 } 34116 34117 // Check if the string contains any keywords. 34118 // None are required. 34119 var tap = entry.indexOf("tap") >= 0; 34120 var drag = entry.indexOf("drag") >= 0; 34121 var fixed = entry.indexOf("fixed") >= 0; 34122 var snap = entry.indexOf("snap") >= 0; 34123 var hover = entry.indexOf("hover") >= 0; 34124 var unconstrained = entry.indexOf("unconstrained") >= 0; 34125 34126 if (fixed) { 34127 if (parsed.handles !== 2) { 34128 throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles"); 34129 } 34130 34131 // Use margin to enforce fixed state 34132 testMargin(parsed, parsed.start[1] - parsed.start[0]); 34133 } 34134 34135 if (unconstrained && (parsed.margin || parsed.limit)) { 34136 throw new Error( 34137 "noUiSlider (" + VERSION + "): 'unconstrained' behaviour cannot be used with margin or limit" 34138 ); 34139 } 34140 34141 parsed.events = { 34142 tap: tap || snap, 34143 drag: drag, 34144 fixed: fixed, 34145 snap: snap, 34146 hover: hover, 34147 unconstrained: unconstrained 34148 }; 34149 } 34150 34151 function testTooltips(parsed, entry) { 34152 if (entry === false) { 34153 return; 34154 } 34155 34156 if (entry === true) { 34157 parsed.tooltips = []; 34158 34159 for (var i = 0; i < parsed.handles; i++) { 34160 parsed.tooltips.push(true); 34161 } 34162 } else { 34163 parsed.tooltips = asArray(entry); 34164 34165 if (parsed.tooltips.length !== parsed.handles) { 34166 throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles."); 34167 } 34168 34169 parsed.tooltips.forEach(function(formatter) { 34170 if ( 34171 typeof formatter !== "boolean" && 34172 (typeof formatter !== "object" || typeof formatter.to !== "function") 34173 ) { 34174 throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'."); 34175 } 34176 }); 34177 } 34178 } 34179 34180 function testAriaFormat(parsed, entry) { 34181 parsed.ariaFormat = entry; 34182 validateFormat(entry); 34183 } 34184 34185 function testFormat(parsed, entry) { 34186 parsed.format = entry; 34187 validateFormat(entry); 34188 } 34189 34190 function testKeyboardSupport(parsed, entry) { 34191 parsed.keyboardSupport = entry; 34192 34193 if (typeof entry !== "boolean") { 34194 throw new Error("noUiSlider (" + VERSION + "): 'keyboardSupport' option must be a boolean."); 34195 } 34196 } 34197 34198 function testDocumentElement(parsed, entry) { 34199 // This is an advanced option. Passed values are used without validation. 34200 parsed.documentElement = entry; 34201 } 34202 34203 function testCssPrefix(parsed, entry) { 34204 if (typeof entry !== "string" && entry !== false) { 34205 throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`."); 34206 } 34207 34208 parsed.cssPrefix = entry; 34209 } 34210
34211 function testCssClasses(parsed, entry) { 34212 if (typeof entry !== "object") { 34213 throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object."); 34214 } 34215 34216 if (typeof parsed.cssPrefix === "string") { 34217 parsed.cssClasses = {}; 34218 34219 for (var key in entry) { 34220 if (!entry.hasOwnProperty(key)) { 34221 continue; 34222 } 34223 34224 parsed.cssClasses[key] = parsed.cssPrefix + entry[key]; 34225 } 34226 } else { 34227 parsed.cssClasses = entry; 34228 } 34229 } 34230 34231 // Test all developer settings and parse to assumption-safe values. 34232 function testOptions(options) { 34233 // To prove a fix for #537, freeze options here. 34234 // If the object is modified, an error will be thrown. 34235 // Object.freeze(options); 34236 34237 var parsed = { 34238 margin: 0, 34239 limit: 0, 34240 padding: 0, 34241 animate: true, 34242 animationDuration: 300, 34243 ariaFormat: defaultFormatter, 34244 format: defaultFormatter 34245 }; 34246 34247 // Tests are executed in the order they are presented here. 34248 var tests = { 34249 step: { r: false, t: testStep }, 34250 start: { r: true, t: testStart }, 34251 connect: { r: true, t: testConnect }, 34252 direction: { r: true, t: testDirection }, 34253 snap: { r: false, t: testSnap }, 34254 animate: { r: false, t: testAnimate }, 34255 animationDuration: { r: false, t: testAnimationDuration }, 34256 range: { r: true, t: testRange }, 34257 orientation: { r: false, t: testOrientation }, 34258 margin: { r: false, t: testMargin }, 34259 limit: { r: false, t: testLimit }, 34260 padding: { r: false, t: testPadding }, 34261 behaviour: { r: true, t: testBehaviour }, 34262 ariaFormat: { r: false, t: testAriaFormat }, 34263 format: { r: false, t: testFormat }, 34264 tooltips: { r: false, t: testTooltips }, 34265 keyboardSupport: { r: true, t: testKeyboardSupport }, 34266 documentElement: { r: false, t: testDocumentElement }, 34267 cssPrefix: { r: true, t: testCssPrefix },
34268 cssClasses: { r: true, t: testCssClasses } 34269 }; 34270 34271 var defaults = { 34272 connect: false, 34273 direction: "ltr", 34274 behaviour: "tap", 34275 orientation: "horizontal", 34276 keyboardSupport: true, 34277 cssPrefix: "noUi-", 34278 cssClasses: { 34279 target: "target", 34280 base: "base", 34281 origin: "origin", 34282 handle: "handle", 34283 handleLower: "handle-lower", 34284 handleUpper: "handle-upper", 34285 horizontal: "horizontal", 34286 vertical: "vertical", 34287 background: "background", 34288 connect: "connect", 34289 connects: "connects", 34290 ltr: "ltr", 34291 rtl: "rtl", 34292 draggable: "draggable", 34293 drag: "state-drag", 34294 tap: "state-tap", 34295 active: "active", 34296 tooltip: "tooltip", 34297 pips: "pips", 34298 pipsHorizontal: "pips-horizontal", 34299 pipsVertical: "pips-vertical", 34300 marker: "marker", 34301 markerHorizontal: "marker-horizontal", 34302 markerVertical: "marker-vertical", 34303 markerNormal: "marker-normal", 34304 markerLarge: "marker-large", 34305 markerSub: "marker-sub", 34306 value: "value", 34307 valueHorizontal: "value-horizontal", 34308 valueVertical: "value-vertical", 34309 valueNormal: "value-normal", 34310 valueLarge: "value-large", 34311 valueSub: "value-sub" 34312 } 34313 }; 34314 34315 // AriaFormat defaults to regular format, if any. 34316 if (options.format && !options.ariaFormat) { 34317 options.ariaFormat = options.format; 34318 } 34319 34320 // Run all options through a testing mechanism to ensure correct 34321 // input. It should be noted that options might get modified to 34322 // be handled properly. E.g. wrapping integers in arrays. 34323 Object.keys(tests).forEach(function(name) { 34324 // If the option isn't set, but it is required, throw an error. 34325 if (!isSet(options[name]) && defaults[name] === undefined) { 34326 if (tests[name].r) { 34327 throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required."); 34328 } 34329 34330 return true; 34331 } 34332 34333 tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]); 34334 }); 34335 34336 // Forward pips options 34337 parsed.pips = options.pips; 34338 34339 // All recent browsers accept unprefixed transform. 34340 // We need -ms- for IE9 and -webkit- for older Android; 34341 // Assume use of -webkit- if unprefixed and -ms- are not supported. 34342 // https://caniuse.com/#feat=transforms2d 34343 var d = document.createElement("div"); 34344 var msPrefix = d.style.msTransform !== undefined; 34345 var noPrefix = d.style.transform !== undefined; 34346 34347 parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform"; 34348 34349 // Pips don't move, so we can place them using left/top. 34350 var styles = [["left", "top"], ["right", "bottom"]]; 34351 34352 parsed.style = styles[parsed.dir][parsed.ort]; 34353 34354 return parsed; 34355 } 34356 34357 function scope(target, options, originalOptions) { 34358 var actions = getActions(); 34359 var supportsTouchActionNone = getSupportsTouchActionNone(); 34360 var supportsPassive = supportsTouchActionNone && getSupportsPassive(); 34361 34362 // All variables local to 'scope' are prefixed with 'scope_' 34363 var scope_Target = target; 34364 var scope_Locations = []; 34365 var scope_Base; 34366 var scope_Handles; 34367 var scope_HandleNumbers = []; 34368 var scope_ActiveHandlesCount = 0; 34369 var scope_Connects; 34370 var scope_Spectrum = options.spectrum; 34371 var scope_Values = []; 34372 var scope_Events = {}; 34373 var scope_Self; 34374 var scope_Pips; 34375 var scope_Document = target.ownerDocument; 34376 var scope_DocumentElement = options.documentElement || scope_Document.documentElement; 34377 var scope_Body = scope_Document.body; 34378 34379 // Pips constants 34380 var PIPS_NONE = -1; 34381 var PIPS_NO_VALUE = 0; 34382 var PIPS_LARGE_VALUE = 1; 34383 var PIPS_SMALL_VALUE = 2; 34384 34385 // For horizontal sliders in standard ltr documents, 34386 // make .noUi-origin overflow to the left so the document doesn't scroll. 34387 var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100; 34388 34389 // Creates a node, adds it to target, returns the new node. 34390 function addNodeTo(addTarget, className) { 34391 var div = scope_Document.createElement("div"); 34392 34393 if (className) { 34394 addClass(div, className); 34395 } 34396 34397 addTarget.appendChild(div); 34398 34399 return div; 34400 } 34401 34402 // Append a origin to the base 34403 function addOrigin(base, handleNumber) {
34404 var origin = addNodeTo(base, options.cssClasses.origin); 34405 var handle = addNodeTo(origin, options.cssClasses.handle); 34406 34407 handle.setAttribute("data-handle", handleNumber); 34408 34409 if (options.keyboardSupport) { 34410 // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex 34411 // 0 = focusable and reachable 34412 handle.setAttribute("tabindex", "0"); 34413 } 34414 34415 handle.setAttribute("role", "slider"); 34416 handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal"); 34417 34418 if (handleNumber === 0) { 34419 addClass(handle, options.cssClasses.handleLower); 34420 } else if (handleNumber === options.handles - 1) { 34421 addClass(handle, options.cssClasses.handleUpper); 34422 } 34423 34424 return origin; 34425 } 34426 34427 // Insert nodes for connect elements 34428 function addConnect(base, add) { 34429 if (!add) { 34430 return false; 34431 } 34432 34433 return addNodeTo(base, options.cssClasses.connect); 34434 } 34435 34436 // Add handles to the slider base. 34437 function addElements(connectOptions, base) { 34438 var connectBase = addNodeTo(base, options.cssClasses.connects); 34439 34440 scope_Handles = []; 34441 scope_Connects = []; 34442 34443 scope_Connects.push(addConnect(connectBase, connectOptions[0])); 34444 34445 // [::::O====O====O====] 34446 // connectOptions = [0, 1, 1, 1] 34447 34448 for (var i = 0; i < options.handles; i++) { 34449 // Keep a list of all added handles. 34450 scope_Handles.push(addOrigin(base, i)); 34451 scope_HandleNumbers[i] = i; 34452 scope_Connects.push(addConnect(connectBase, connectOptions[i + 1])); 34453 } 34454 } 34455 34456 // Initialize a single slider. 34457 function addSlider(addTarget) { 34458 // Apply classes and data to the target. 34459 addClass(addTarget, options.cssClasses.target); 34460 34461 if (options.dir === 0) { 34462 addClass(addTarget, options.cssClasses.ltr); 34463 } else { 34464 addClass(addTarget, options.cssClasses.rtl); 34465 } 34466 34467 if (options.ort === 0) { 34468 addClass(addTarget, options.cssClasses.horizontal); 34469 } else { 34470 addClass(addTarget, options.cssClasses.vertical); 34471 } 34472 34473 return addNodeTo(addTarget, options.cssClasses.base); 34474 } 34475 34476 function addTooltip(handle, handleNumber) { 34477 if (!options.tooltips[handleNumber]) { 34478 return false; 34479 } 34480 34481 return addNodeTo(handle.firstChild, options.cssClasses.tooltip); 34482 } 34483 34484 // The tooltips option is a shorthand for using the 'update' event. 34485 function tooltips() { 34486 // Tooltips are added with options.tooltips in original order. 34487 var tips = scope_Handles.map(addTooltip); 34488 34489 bindEvent("update", function(values, handleNumber, unencoded) { 34490 if (!tips[handleNumber]) { 34491 return; 34492 } 34493 34494 var formattedValue = values[handleNumber]; 34495 34496 if (options.tooltips[handleNumber] !== true) { 34497 formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]); 34498 } 34499 34500 tips[handleNumber].innerHTML = formattedValue; 34501 }); 34502 } 34503 34504 function aria() { 34505 bindEvent("update", function(values, handleNumber, unencoded, tap, positions) { 34506 // Update Aria Values for all handles, as a change in one changes min and max values for the next. 34507 scope_HandleNumbers.forEach(function(index) { 34508 var handle = scope_Handles[index]; 34509 34510 var min = checkHandlePosition(scope_Locations, index, 0, true, true, true); 34511 var max = checkHandlePosition(scope_Locations, index, 100, true, true, true); 34512 34513 var now = positions[index]; 34514 34515 // Formatted value for display 34516 var text = options.ariaFormat.to(unencoded[index]); 34517 34518 // Map to slider range values 34519 min = scope_Spectrum.fromStepping(min).toFixed(1); 34520 max = scope_Spectrum.fromStepping(max).toFixed(1); 34521 now = scope_Spectrum.fromStepping(now).toFixed(1); 34522 34523 handle.children[0].setAttribute("aria-valuemin", min); 34524 handle.children[0].setAttribute("aria-valuemax", max); 34525 handle.children[0].setAttribute("aria-valuenow", now); 34526 handle.children[0].setAttribute("aria-valuetext", text); 34527 }); 34528 }); 34529 } 34530 34531 function getGroup(mode, values, stepped) { 34532 // Use the range. 34533 if (mode === "range" || mode === "steps") { 34534 return scope_Spectrum.xVal; 34535 } 34536 34537 if (mode === "count") { 34538 if (values < 2) { 34539 throw new Error("noUiSlider (" + VERSION + "): 'values' (>= 2) required for mode 'count'."); 34540 } 34541 34542 // Divide 0 - 100 in 'count' parts. 34543 var interval = values - 1; 34544 var spread = 100 / interval; 34545 34546 values = []; 34547 34548 // List these parts and have them handled as 'positions'. 34549 while (interval--) { 34550 values[interval] = interval * spread; 34551 } 34552 34553 values.push(100); 34554 34555 mode = "positions"; 34556 } 34557 34558 if (mode === "positions") { 34559 // Map all percentages to on-range values. 34560 return values.map(function(value) { 34561 return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value); 34562 }); 34563 } 34564 34565 if (mode === "values") { 34566 // If the value must be stepped, it needs to be converted to a percentage first. 34567 if (stepped) { 34568 return values.map(function(value) { 34569 // Convert to percentage, apply step, return to value. 34570 return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value))); 34571 }); 34572 } 34573 34574 // Otherwise, we can simply use the values. 34575 return values; 34576 } 34577 } 34578 34579 function generateSpread(density, mode, group) { 34580 function safeIncrement(value, increment) { 34581 // Avoid floating point variance by dropping the smallest decimal places. 34582 return (value + increment).toFixed(7) / 1; 34583 } 34584 34585 var indexes = {}; 34586 var firstInRange = scope_Spectrum.xVal[0]; 34587 var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1]; 34588 var ignoreFirst = false;
vendor: 4,581 bytes, lines 34589-34698
34589 var ignoreLast = false; 34590 var prevPct = 0; 34591 34592 // Create a copy of the group, sort it and filter away all duplicates. 34593 group = unique( 34594 group.slice().sort(function(a, b) { 34595 return a - b; 34596 }) 34597 ); 34598 34599 // Make sure the range starts with the first element. 34600 if (group[0] !== firstInRange) { 34601 group.unshift(firstInRange); 34602 ignoreFirst = true; 34603 } 34604 34605 // Likewise for the last one. 34606 if (group[group.length - 1] !== lastInRange) { 34607 group.push(lastInRange); 34608 ignoreLast = true; 34609 } 34610 34611 group.forEach(function(current, index) { 34612 // Get the current step and the lower + upper positions. 34613 var step; 34614 var i; 34615 var q; 34616 var low = current; 34617 var high = group[index + 1]; 34618 var newPct; 34619 var pctDifference; 34620 var pctPos; 34621 var type; 34622 var steps; 34623 var realSteps; 34624 var stepSize; 34625 var isSteps = mode === "steps"; 34626 34627 // When using 'steps' mode, use the provided steps. 34628 // Otherwise, we'll step on to the next subrange. 34629 if (isSteps) { 34630 step = scope_Spectrum.xNumSteps[index]; 34631 } 34632 34633 // Default to a 'full' step. 34634 if (!step) { 34635 step = high - low; 34636 } 34637 34638 // Low can be 0, so test for false. If high is undefined, 34639 // we are at the last subrange. Index 0 is already handled. 34640 if (low === false || high === undefined) { 34641 return; 34642 } 34643 34644 // Make sure step isn't 0, which would cause an infinite loop (#654) 34645 step = Math.max(step, 0.0000001); 34646 34647 // Find all steps in the subrange. 34648 for (i = low; i <= high; i = safeIncrement(i, step)) { 34649 // Get the percentage value for the current step, 34650 // calculate the size for the subrange. 34651 newPct = scope_Spectrum.toStepping(i); 34652 pctDifference = newPct - prevPct; 34653 34654 steps = pctDifference / density; 34655 realSteps = Math.round(steps); 34656 34657 // This ratio represents the amount of percentage-space a point indicates. 34658 // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided. 34659 // Round the percentage offset to an even number, then divide by two 34660 // to spread the offset on both sides of the range. 34661 stepSize = pctDifference / realSteps; 34662 34663 // Divide all points evenly, adding the correct number to this subrange. 34664 // Run up to <= so that 100% gets a point, event if ignoreLast is set. 34665 for (q = 1; q <= realSteps; q += 1) { 34666 // The ratio between the rounded value and the actual size might be ~1% off. 34667 // Correct the percentage offset by the number of points 34668 // per subrange. density = 1 will result in 100 points on the 34669 // full range, 2 for 50, 4 for 25, etc. 34670 pctPos = prevPct + q * stepSize; 34671 indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0]; 34672 } 34673 34674 // Determine the point type. 34675 type = group.indexOf(i) > -1 ? PIPS_LARGE_VALUE : isSteps ? PIPS_SMALL_VALUE : PIPS_NO_VALUE; 34676 34677 // Enforce the 'ignoreFirst' option by overwriting the type for 0. 34678 if (!index && ignoreFirst) { 34679 type = 0; 34680 } 34681 34682 if (!(i === high && ignoreLast)) { 34683 // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value. 34684 indexes[newPct.toFixed(5)] = [i, type]; 34685 } 34686 34687 // Update the percentage count. 34688 prevPct = newPct; 34689 } 34690 }); 34691 34692 return indexes; 34693 } 34694 34695 function addMarking(spread, filterFunc, formatter) { 34696 var element = scope_Document.createElement("div"); 34697 34698 var valueSizeClasses = [];
34699 valueSizeClasses[PIPS_NO_VALUE] = options.cssClasses.valueNormal; 34700 valueSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.valueLarge; 34701 valueSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.valueSub; 34702 34703 var markerSizeClasses = []; 34704 markerSizeClasses[PIPS_NO_VALUE] = options.cssClasses.markerNormal; 34705 markerSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.markerLarge; 34706 markerSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.markerSub; 34707 34708 var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical]; 34709 var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical]; 34710 34711 addClass(element, options.cssClasses.pips); 34712 addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical); 34713 34714 function getClasses(type, source) { 34715 var a = source === options.cssClasses.value; 34716 var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses; 34717 var sizeClasses = a ? valueSizeClasses : markerSizeClasses; 34718 34719 return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type]; 34720 } 34721 34722 function addSpread(offset, value, type) { 34723 // Apply the filter function, if it is set. 34724 type = filterFunc ? filterFunc(value, type) : type; 34725 34726 if (type === PIPS_NONE) { 34727 return; 34728 } 34729 34730 // Add a marker for every point 34731 var node = addNodeTo(element, false); 34732 node.className = getClasses(type, options.cssClasses.marker); 34733 node.style[options.style] = offset + "%"; 34734 34735 // Values are only appended for points marked '1' or '2'. 34736 if (type > PIPS_NO_VALUE) { 34737 node = addNodeTo(element, false); 34738 node.className = getClasses(type, options.cssClasses.value); 34739 node.setAttribute("data-value", value); 34740 node.style[options.style] = offset + "%"; 34741 node.innerHTML = formatter.to(value); 34742 } 34743 } 34744 34745 // Append all points. 34746 Object.keys(spread).forEach(function(offset) { 34747 addSpread(offset, spread[offset][0], spread[offset][1]); 34748 }); 34749 34750 return element; 34751 } 34752 34753 function removePips() { 34754 if (scope_Pips) { 34755 removeElement(scope_Pips); 34756 scope_Pips = null; 34757 } 34758 } 34759 34760 function pips(grid) { 34761 // Fix #669 34762 removePips(); 34763 34764 var mode = grid.mode; 34765 var density = grid.density || 1; 34766 var filter = grid.filter || false; 34767 var values = grid.values || false; 34768 var stepped = grid.stepped || false; 34769 var group = getGroup(mode, values, stepped); 34770 var spread = generateSpread(density, mode, group); 34771 var format = grid.format || { 34772 to: Math.round 34773 }; 34774 34775 scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format)); 34776 34777 return scope_Pips; 34778 } 34779 34780 // Shorthand for base dimensions. 34781 function baseSize() { 34782 var rect = scope_Base.getBoundingClientRect(); 34783 var alt = "offset" + ["Width", "Height"][options.ort]; 34784 return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt]; 34785 } 34786 34787 // Handler for attaching events trough a proxy. 34788 function attachEvent(events, element, callback, data) { 34789 // This function can be used to 'filter' events to the slider. 34790 // element is a node, not a nodeList 34791 34792 var method = function(e) { 34793 e = fixEvent(e, data.pageOffset, data.target || element); 34794 34795 // fixEvent returns false if this event has a different target 34796 // when handling (multi-) touch events; 34797 if (!e) { 34798 return false;
vendor: 15,307 bytes, lines 34799-35174
34799 } 34800 34801 // doNotReject is passed by all end events to make sure released touches 34802 // are not rejected, leaving the slider "stuck" to the cursor; 34803 if (scope_Target.hasAttribute("disabled") && !data.doNotReject) { 34804 return false; 34805 } 34806 34807 // Stop if an active 'tap' transition is taking place. 34808 if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) { 34809 return false; 34810 } 34811 34812 // Ignore right or middle clicks on start #454 34813 if (events === actions.start && e.buttons !== undefined && e.buttons > 1) { 34814 return false; 34815 } 34816 34817 // Ignore right or middle clicks on start #454 34818 if (data.hover && e.buttons) { 34819 return false; 34820 } 34821 34822 // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS. 34823 // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support 34824 // touch-action: manipulation, but that allows panning, which breaks 34825 // sliders after zooming/on non-responsive pages. 34826 // See: https://bugs.webkit.org/show_bug.cgi?id=133112 34827 if (!supportsPassive) { 34828 e.preventDefault(); 34829 } 34830 34831 e.calcPoint = e.points[options.ort]; 34832 34833 // Call the event handler with the event [ and additional data ]. 34834 callback(e, data); 34835 }; 34836 34837 var methods = []; 34838 34839 // Bind a closure on the target for every event type. 34840 events.split(" ").forEach(function(eventName) { 34841 element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false); 34842 methods.push([eventName, method]); 34843 }); 34844 34845 return methods; 34846 } 34847 34848 // Provide a clean event with standardized offset values. 34849 function fixEvent(e, pageOffset, eventTarget) { 34850 // Filter the event to register the type, which can be 34851 // touch, mouse or pointer. Offset changes need to be 34852 // made on an event specific basis. 34853 var touch = e.type.indexOf("touch") === 0; 34854 var mouse = e.type.indexOf("mouse") === 0; 34855 var pointer = e.type.indexOf("pointer") === 0; 34856 34857 var x; 34858 var y; 34859 34860 // IE10 implemented pointer events with a prefix; 34861 if (e.type.indexOf("MSPointer") === 0) { 34862 pointer = true; 34863 } 34864 34865 // The only thing one handle should be concerned about is the touches that originated on top of it. 34866 if (touch) { 34867 // Returns true if a touch originated on the target. 34868 var isTouchOnTarget = function(checkTouch) { 34869 return checkTouch.target === eventTarget || eventTarget.contains(checkTouch.target); 34870 }; 34871 34872 // In the case of touchstart events, we need to make sure there is still no more than one 34873 // touch on the target so we look amongst all touches. 34874 if (e.type === "touchstart") { 34875 var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget); 34876 34877 // Do not support more than one touch per handle. 34878 if (targetTouches.length > 1) { 34879 return false; 34880 } 34881 34882 x = targetTouches[0].pageX; 34883 y = targetTouches[0].pageY; 34884 } else { 34885 // In the other cases, find on changedTouches is enough. 34886 var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget); 34887 34888 // Cancel if the target touch has not moved. 34889 if (!targetTouch) { 34890 return false; 34891 } 34892 34893 x = targetTouch.pageX; 34894 y = targetTouch.pageY; 34895 } 34896 } 34897 34898 pageOffset = pageOffset || getPageOffset(scope_Document); 34899 34900 if (mouse || pointer) { 34901 x = e.clientX + pageOffset.x; 34902 y = e.clientY + pageOffset.y; 34903 } 34904 34905 e.pageOffset = pageOffset; 34906 e.points = [x, y]; 34907 e.cursor = mouse || pointer; // Fix #435 34908 34909 return e; 34910 } 34911 34912 // Translate a coordinate in the document to a percentage on the slider 34913 function calcPointToPercentage(calcPoint) { 34914 var location = calcPoint - offset(scope_Base, options.ort); 34915 var proposal = (location * 100) / baseSize(); 34916 34917 // Clamp proposal between 0% and 100% 34918 // Out-of-bound coordinates may occur when .noUi-base pseudo-elements 34919 // are used (e.g. contained handles feature) 34920 proposal = limit(proposal); 34921 34922 return options.dir ? 100 - proposal : proposal; 34923 } 34924 34925 // Find handle closest to a certain percentage on the slider 34926 function getClosestHandle(proposal) { 34927 var closest = 100; 34928 var handleNumber = false; 34929 34930 scope_Handles.forEach(function(handle, index) { 34931 // Disabled handles are ignored 34932 if (handle.hasAttribute("disabled")) { 34933 return; 34934 } 34935 34936 var pos = Math.abs(scope_Locations[index] - proposal); 34937 34938 if (pos < closest || (pos === 100 && closest === 100)) { 34939 handleNumber = index; 34940 closest = pos; 34941 } 34942 }); 34943 34944 return handleNumber; 34945 } 34946 34947 // Fire 'end' when a mouse or pen leaves the document. 34948 function documentLeave(event, data) { 34949 if (event.type === "mouseout" && event.target.nodeName === "HTML" && event.relatedTarget === null) { 34950 eventEnd(event, data); 34951 } 34952 } 34953 34954 // Handle movement on document for handle and range drag. 34955 function eventMove(event, data) { 34956 // Fix #498 34957 // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty). 34958 // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero 34959 // IE9 has .buttons and .which zero on mousemove. 34960 // Firefox breaks the spec MDN defines. 34961 if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) { 34962 return eventEnd(event, data); 34963 } 34964 34965 // Check if we are moving up or down 34966 var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint); 34967 34968 // Convert the movement into a percentage of the slider width/height 34969 var proposal = (movement * 100) / data.baseSize; 34970 34971 moveHandles(movement > 0, proposal, data.locations, data.handleNumbers); 34972 } 34973 34974 // Unbind move events on document, call callbacks. 34975 function eventEnd(event, data) { 34976 // The handle is no longer active, so remove the class. 34977 if (data.handle) { 34978 removeClass(data.handle, options.cssClasses.active); 34979 scope_ActiveHandlesCount -= 1; 34980 } 34981 34982 // Unbind the move and end events, which are added on 'start'. 34983 data.listeners.forEach(function(c) { 34984 scope_DocumentElement.removeEventListener(c[0], c[1]); 34985 }); 34986 34987 if (scope_ActiveHandlesCount === 0) { 34988 // Remove dragging class. 34989 removeClass(scope_Target, options.cssClasses.drag); 34990 setZindex(); 34991 34992 // Remove cursor styles and text-selection events bound to the body. 34993 if (event.cursor) { 34994 scope_Body.style.cursor = ""; 34995 scope_Body.removeEventListener("selectstart", preventDefault); 34996 } 34997 } 34998 34999 data.handleNumbers.forEach(function(handleNumber) { 35000 fireEvent("change", handleNumber); 35001 fireEvent("set", handleNumber); 35002 fireEvent("end", handleNumber); 35003 }); 35004 } 35005 35006 // Bind move events on document. 35007 function eventStart(event, data) { 35008 var handle; 35009 if (data.handleNumbers.length === 1) { 35010 var handleOrigin = scope_Handles[data.handleNumbers[0]]; 35011 35012 // Ignore 'disabled' handles 35013 if (handleOrigin.hasAttribute("disabled")) { 35014 return false; 35015 } 35016 35017 handle = handleOrigin.children[0]; 35018 scope_ActiveHandlesCount += 1; 35019 35020 // Mark the handle as 'active' so it can be styled. 35021 addClass(handle, options.cssClasses.active); 35022 } 35023 35024 // A drag should never propagate up to the 'tap' event. 35025 event.stopPropagation(); 35026 35027 // Record the event listeners. 35028 var listeners = []; 35029 35030 // Attach the move and end events. 35031 var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, { 35032 // The event target has changed so we need to propagate the original one so that we keep 35033 // relying on it to extract target touches. 35034 target: event.target, 35035 handle: handle, 35036 listeners: listeners, 35037 startCalcPoint: event.calcPoint, 35038 baseSize: baseSize(), 35039 pageOffset: event.pageOffset, 35040 handleNumbers: data.handleNumbers, 35041 buttonsProperty: event.buttons, 35042 locations: scope_Locations.slice() 35043 }); 35044 35045 var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, { 35046 target: event.target, 35047 handle: handle, 35048 listeners: listeners, 35049 doNotReject: true, 35050 handleNumbers: data.handleNumbers 35051 }); 35052 35053 var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, { 35054 target: event.target, 35055 handle: handle, 35056 listeners: listeners, 35057 doNotReject: true, 35058 handleNumbers: data.handleNumbers 35059 }); 35060 35061 // We want to make sure we pushed the listeners in the listener list rather than creating 35062 // a new one as it has already been passed to the event handlers. 35063 listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent)); 35064 35065 // Text selection isn't an issue on touch devices, 35066 // so adding cursor styles can be skipped. 35067 if (event.cursor) { 35068 // Prevent the 'I' cursor and extend the range-drag cursor. 35069 scope_Body.style.cursor = getComputedStyle(event.target).cursor; 35070 35071 // Mark the target with a dragging state. 35072 if (scope_Handles.length > 1) { 35073 addClass(scope_Target, options.cssClasses.drag); 35074 } 35075 35076 // Prevent text selection when dragging the handles. 35077 // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move, 35078 // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52, 35079 // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there. 35080 // The 'cursor' flag is false. 35081 // See: http://caniuse.com/#search=selectstart 35082 scope_Body.addEventListener("selectstart", preventDefault, false); 35083 } 35084 35085 data.handleNumbers.forEach(function(handleNumber) { 35086 fireEvent("start", handleNumber); 35087 }); 35088 } 35089 35090 // Move closest handle to tapped location. 35091 function eventTap(event) { 35092 // The tap event shouldn't propagate up 35093 event.stopPropagation(); 35094 35095 var proposal = calcPointToPercentage(event.calcPoint); 35096 var handleNumber = getClosestHandle(proposal); 35097 35098 // Tackle the case that all handles are 'disabled'. 35099 if (handleNumber === false) { 35100 return false; 35101 } 35102 35103 // Flag the slider as it is now in a transitional state. 35104 // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that. 35105 if (!options.events.snap) { 35106 addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration); 35107 } 35108 35109 setHandle(handleNumber, proposal, true, true); 35110 35111 setZindex(); 35112 35113 fireEvent("slide", handleNumber, true); 35114 fireEvent("update", handleNumber, true); 35115 fireEvent("change", handleNumber, true); 35116 fireEvent("set", handleNumber, true); 35117 35118 if (options.events.snap) { 35119 eventStart(event, { handleNumbers: [handleNumber] }); 35120 } 35121 } 35122 35123 // Fires a 'hover' event for a hovered mouse/pen position. 35124 function eventHover(event) { 35125 var proposal = calcPointToPercentage(event.calcPoint); 35126 35127 var to = scope_Spectrum.getStep(proposal); 35128 var value = scope_Spectrum.fromStepping(to); 35129 35130 Object.keys(scope_Events).forEach(function(targetEvent) { 35131 if ("hover" === targetEvent.split(".")[0]) { 35132 scope_Events[targetEvent].forEach(function(callback) { 35133 callback.call(scope_Self, value); 35134 }); 35135 } 35136 }); 35137 } 35138 35139 // Attach events to several slider parts. 35140 function bindSliderEvents(behaviour) { 35141 // Attach the standard drag event to the handles. 35142 if (!behaviour.fixed) { 35143 scope_Handles.forEach(function(handle, index) { 35144 // These events are only bound to the visual handle 35145 // element, not the 'real' origin element. 35146 attachEvent(actions.start, handle.children[0], eventStart, { 35147 handleNumbers: [index] 35148 }); 35149 }); 35150 } 35151 35152 // Attach the tap event to the slider base. 35153 if (behaviour.tap) { 35154 attachEvent(actions.start, scope_Base, eventTap, {}); 35155 } 35156 35157 // Fire hover events 35158 if (behaviour.hover) { 35159 attachEvent(actions.move, scope_Base, eventHover, { 35160 hover: true 35161 }); 35162 } 35163 35164 // Make the range draggable. 35165 if (behaviour.drag) { 35166 scope_Connects.forEach(function(connect, index) { 35167 if (connect === false || index === 0 || index === scope_Connects.length - 1) { 35168 return; 35169 } 35170 35171 var handleBefore = scope_Handles[index - 1]; 35172 var handleAfter = scope_Handles[index]; 35173 var eventHolders = [connect]; 35174
35175 addClass(connect, options.cssClasses.draggable); 35176 35177 // When the range is fixed, the entire range can 35178 // be dragged by the handles. The handle in the first 35179 // origin will propagate the start event upward, 35180 // but it needs to be bound manually on the other. 35181 if (behaviour.fixed) { 35182 eventHolders.push(handleBefore.children[0]); 35183 eventHolders.push(handleAfter.children[0]); 35184 } 35185 35186 eventHolders.forEach(function(eventHolder) { 35187 attachEvent(actions.start, eventHolder, eventStart, { 35188 handles: [handleBefore, handleAfter], 35189 handleNumbers: [index - 1, index] 35190 }); 35191 }); 35192 }); 35193 } 35194 } 35195 35196 // Attach an event to this slider, possibly including a namespace 35197 function bindEvent(namespacedEvent, callback) { 35198 scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || []; 35199 scope_Events[namespacedEvent].push(callback); 35200 35201 // If the event bound is 'update,' fire it immediately for all handles. 35202 if (namespacedEvent.split(".")[0] === "update") { 35203 scope_Handles.forEach(function(a, index) { 35204 fireEvent("update", index); 35205 }); 35206 } 35207 } 35208 35209 // Undo attachment of event 35210 function removeEvent(namespacedEvent) { 35211 var event = namespacedEvent && namespacedEvent.split(".")[0]; 35212 var namespace = event && namespacedEvent.substring(event.length); 35213 35214 Object.keys(scope_Events).forEach(function(bind) { 35215 var tEvent = bind.split(".")[0]; 35216 var tNamespace = bind.substring(tEvent.length); 35217 35218 if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) { 35219 delete scope_Events[bind]; 35220 } 35221 }); 35222 } 35223 35224 // External event handling 35225 function fireEvent(eventName, handleNumber, tap) { 35226 Object.keys(scope_Events).forEach(function(targetEvent) { 35227 var eventType = targetEvent.split(".")[0]; 35228 35229 if (eventName === eventType) { 35230 scope_Events[targetEvent].forEach(function(callback) { 35231 callback.call( 35232 // Use the slider public API as the scope ('this') 35233 scope_Self, 35234 // Return values as array, so arg_1[arg_2] is always valid. 35235 scope_Values.map(options.format.to), 35236 // Handle index, 0 or 1 35237 handleNumber, 35238 // Un-formatted slider values 35239 scope_Values.slice(), 35240 // Event is fired by tap, true or false 35241 tap || false, 35242 // Left offset of the handle, in relation to the slider 35243 scope_Locations.slice() 35244 ); 35245 }); 35246 } 35247 }); 35248 } 35249 35250 function toPct(pct) { 35251 return pct + "%"; 35252 } 35253 35254 // Split out the handle positioning logic so the Move event can use it, too 35255 function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) { 35256 // For sliders with multiple handles, limit movement to the other handle. 35257 // Apply the margin option by adding it to the handle positions. 35258 if (scope_Handles.length > 1 && !options.events.unconstrained) { 35259 if (lookBackward && handleNumber > 0) { 35260 to = Math.max(to, reference[handleNumber - 1] + options.margin); 35261 } 35262 35263 if (lookForward && handleNumber < scope_Handles.length - 1) { 35264 to = Math.min(to, reference[handleNumber + 1] - options.margin); 35265 } 35266 } 35267 35268 // The limit option has the opposite effect, limiting handles to a 35269 // maximum distance from another. Limit must be > 0, as otherwise 35270 // handles would be unmovable. 35271 if (scope_Handles.length > 1 && options.limit) { 35272 if (lookBackward && handleNumber > 0) { 35273 to = Math.min(to, reference[handleNumber - 1] + options.limit); 35274 } 35275 35276 if (lookForward && handleNumber < scope_Handles.length - 1) { 35277 to = Math.max(to, reference[handleNumber + 1] - options.limit); 35278 } 35279 } 35280 35281 // The padding option keeps the handles a certain distance from the 35282 // edges of the slider. Padding must be > 0. 35283 if (options.padding) { 35284 if (handleNumber === 0) { 35285 to = Math.max(to, options.padding[0]); 35286 } 35287 35288 if (handleNumber === scope_Handles.length - 1) { 35289 to = Math.min(to, 100 - options.padding[1]); 35290 } 35291 } 35292 35293 to = scope_Spectrum.getStep(to); 35294 35295 // Limit percentage to the 0 - 100 range 35296 to = limit(to); 35297 35298 // Return false if handle can't move 35299 if (to === reference[handleNumber] && !getValue) { 35300 return false;
35301 } 35302 35303 return to; 35304 } 35305 35306 // Uses slider orientation to create CSS rules. a = base value; 35307 function inRuleOrder(v, a) { 35308 var o = options.ort; 35309 return (o ? a : v) + ", " + (o ? v : a); 35310 } 35311 35312 // Moves handle(s) by a percentage 35313 // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...]) 35314 function moveHandles(upward, proposal, locations, handleNumbers) { 35315 var proposals = locations.slice(); 35316 35317 var b = [!upward, upward]; 35318 var f = [upward, !upward]; 35319 35320 // Copy handleNumbers so we don't change the dataset 35321 handleNumbers = handleNumbers.slice(); 35322 35323 // Check to see which handle is 'leading'. 35324 // If that one can't move the second can't either. 35325 if (upward) { 35326 handleNumbers.reverse(); 35327 } 35328 35329 // Step 1: get the maximum percentage that any of the handles can move 35330 if (handleNumbers.length > 1) { 35331 handleNumbers.forEach(function(handleNumber, o) { 35332 var to = checkHandlePosition( 35333 proposals, 35334 handleNumber, 35335 proposals[handleNumber] + proposal, 35336 b[o], 35337 f[o], 35338 false 35339 ); 35340 35341 // Stop if one of the handles can't move. 35342 if (to === false) { 35343 proposal = 0; 35344 } else { 35345 proposal = to - proposals[handleNumber]; 35346 proposals[handleNumber] = to; 35347 } 35348 }); 35349 } 35350 35351 // If using one handle, check backward AND forward 35352 else { 35353 b = f = [true]; 35354 } 35355 35356 var state = false; 35357 35358 // Step 2: Try to set the handles with the found percentage 35359 handleNumbers.forEach(function(handleNumber, o) { 35360 state = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state; 35361 }); 35362 35363 // Step 3: If a handle moved, fire events 35364 if (state) { 35365 handleNumbers.forEach(function(handleNumber) { 35366 fireEvent("update", handleNumber); 35367 fireEvent("slide", handleNumber); 35368 }); 35369 } 35370 } 35371 35372 // Takes a base value and an offset. This offset is used for the connect bar size. 35373 // In the initial design for this feature, the origin element was 1% wide. 35374 // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature 35375 // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223 35376 function transformDirection(a, b) { 35377 return options.dir ? 100 - a - b : a; 35378 } 35379 35380 // Updates scope_Locations and scope_Values, updates visual state 35381 function updateHandlePosition(handleNumber, to) { 35382 // Update locations. 35383 scope_Locations[handleNumber] = to; 35384 35385 // Convert the value to the slider stepping/range. 35386 scope_Values[handleNumber] = scope_Spectrum.fromStepping(to); 35387 35388 var rule = "translate(" + inRuleOrder(toPct(transformDirection(to, 0) - scope_DirOffset), "0") + ")"; 35389 scope_Handles[handleNumber].style[options.transformRule] = rule; 35390 35391 updateConnect(handleNumber); 35392 updateConnect(handleNumber + 1); 35393 } 35394 35395 // Handles before the slider middle are stacked later = higher, 35396 // Handles after the middle later is lower 35397 // [[7] [8] .......... | .......... [5] [4] 35398 function setZindex() { 35399 scope_HandleNumbers.forEach(function(handleNumber) { 35400 var dir = scope_Locations[handleNumber] > 50 ? -1 : 1; 35401 var zIndex = 3 + (scope_Handles.length + dir * handleNumber); 35402 scope_Handles[handleNumber].style.zIndex = zIndex; 35403 }); 35404 } 35405 35406 // Test suggested values and apply margin, step. 35407 function setHandle(handleNumber, to, lookBackward, lookForward) { 35408 to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false); 35409 35410 if (to === false) { 35411 return false;
35412 } 35413 35414 updateHandlePosition(handleNumber, to); 35415 35416 return true; 35417 } 35418 35419 // Updates style attribute for connect nodes 35420 function updateConnect(index) { 35421 // Skip connects set to false 35422 if (!scope_Connects[index]) { 35423 return; 35424 } 35425 35426 var l = 0; 35427 var h = 100; 35428 35429 if (index !== 0) { 35430 l = scope_Locations[index - 1]; 35431 } 35432 35433 if (index !== scope_Connects.length - 1) { 35434 h = scope_Locations[index]; 35435 } 35436 35437 // We use two rules: 35438 // 'translate' to change the left/top offset; 35439 // 'scale' to change the width of the element; 35440 // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base) 35441 var connectWidth = h - l; 35442 var translateRule = "translate(" + inRuleOrder(toPct(transformDirection(l, connectWidth)), "0") + ")"; 35443 var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")"; 35444 35445 scope_Connects[index].style[options.transformRule] = translateRule + " " + scaleRule; 35446 } 35447 35448 // Parses value passed to .set method. Returns current value if not parse-able. 35449 function resolveToValue(to, handleNumber) { 35450 // Setting with null indicates an 'ignore'. 35451 // Inputting 'false' is invalid. 35452 if (to === null || to === false || to === undefined) { 35453 return scope_Locations[handleNumber]; 35454 } 35455 35456 // If a formatted number was passed, attempt to decode it. 35457 if (typeof to === "number") { 35458 to = String(to); 35459 } 35460 35461 to = options.format.from(to); 35462 to = scope_Spectrum.toStepping(to); 35463 35464 // If parsing the number failed, use the current value. 35465 if (to === false || isNaN(to)) { 35466 return scope_Locations[handleNumber]; 35467 } 35468 35469 return to; 35470 } 35471 35472 // Set the slider value. 35473 function valueSet(input, fireSetEvent) { 35474 var values = asArray(input); 35475 var isInit = scope_Locations[0] === undefined; 35476 35477 // Event fires by default 35478 fireSetEvent = fireSetEvent === undefined ? true : !!fireSetEvent; 35479 35480 // Animation is optional. 35481 // Make sure the initial values were set before using animated placement. 35482 if (options.animate && !isInit) { 35483 addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration); 35484 } 35485 35486 // First pass, without lookAhead but with lookBackward. Values are set from left to right. 35487 scope_HandleNumbers.forEach(function(handleNumber) { 35488 setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false); 35489 }); 35490 35491 // Second pass. Now that all base values are set, apply constraints 35492 scope_HandleNumbers.forEach(function(handleNumber) { 35493 setHandle(handleNumber, scope_Locations[handleNumber], true, true); 35494 }); 35495 35496 setZindex(); 35497 35498 scope_HandleNumbers.forEach(function(handleNumber) { 35499 fireEvent("update", handleNumber); 35500 35501 // Fire the event only for handles that received a new value, as per #579 35502 if (values[handleNumber] !== null && fireSetEvent) { 35503 fireEvent("set", handleNumber); 35504 } 35505 }); 35506 } 35507 35508 // Reset slider to initial values 35509 function valueReset(fireSetEvent) { 35510 valueSet(options.start, fireSetEvent); 35511 } 35512 35513 // Set value for a single handle 35514 function valueSetHandle(handleNumber, value, fireSetEvent) { 35515 var values = []; 35516 35517 // Ensure numeric input 35518 handleNumber = Number(handleNumber); 35519 35520 if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) { 35521 throw new Error("noUiSlider (" + VERSION + "): invalid handle number, got: " + handleNumber); 35522 } 35523 35524 for (var i = 0; i < scope_HandleNumbers.length; i++) { 35525 values[i] = null; 35526 } 35527 35528 values[handleNumber] = value; 35529 35530 valueSet(values, fireSetEvent); 35531 } 35532 35533 // Get the slider value. 35534 function valueGet() { 35535 var values = scope_Values.map(options.format.to); 35536 35537 // If only one handle is used, return a single value. 35538 if (values.length === 1) { 35539 return values[0]; 35540 } 35541 35542 return values; 35543 } 35544 35545 // Removes classes from the root and empties it. 35546 function destroy() {
35547 for (var key in options.cssClasses) { 35548 if (!options.cssClasses.hasOwnProperty(key)) { 35549 continue; 35550 } 35551 removeClass(scope_Target, options.cssClasses[key]); 35552 } 35553 35554 while (scope_Target.firstChild) { 35555 scope_Target.removeChild(scope_Target.firstChild); 35556 } 35557 35558 delete scope_Target.noUiSlider; 35559 } 35560 35561 // Get the current step size for the slider. 35562 function getCurrentStep() { 35563 // Check all locations, map them to their stepping point. 35564 // Get the step point, then find it in the input list. 35565 return scope_Locations.map(function(location, index) { 35566 var nearbySteps = scope_Spectrum.getNearbySteps(location); 35567 var value = scope_Values[index]; 35568 var increment = nearbySteps.thisStep.step; 35569 var decrement = null; 35570 35571 // If the next value in this step moves into the next step, 35572 // the increment is the start of the next step - the current value 35573 if (increment !== false) { 35574 if (value + increment > nearbySteps.stepAfter.startValue) { 35575 increment = nearbySteps.stepAfter.startValue - value; 35576 } 35577 } 35578 35579 // If the value is beyond the starting point 35580 if (value > nearbySteps.thisStep.startValue) { 35581 decrement = nearbySteps.thisStep.step; 35582 } else if (nearbySteps.stepBefore.step === false) { 35583 decrement = false; 35584 } 35585 35586 // If a handle is at the start of a step, it always steps back into the previous step first 35587 else { 35588 decrement = value - nearbySteps.stepBefore.highestStep; 35589 } 35590 35591 // Now, if at the slider edges, there is not in/decrement 35592 if (location === 100) { 35593 increment = null; 35594 } else if (location === 0) { 35595 decrement = null; 35596 } 35597 35598 // As per #391, the comparison for the decrement step can have some rounding issues. 35599 var stepDecimals = scope_Spectrum.countStepDecimals(); 35600 35601 // Round per #391 35602 if (increment !== null && increment !== false) { 35603 increment = Number(increment.toFixed(stepDecimals)); 35604 } 35605 35606 if (decrement !== null && decrement !== false) { 35607 decrement = Number(decrement.toFixed(stepDecimals)); 35608 } 35609 35610 return [decrement, increment]; 35611 }); 35612 } 35613 35614 // Updateable: margin, limit, padding, step, range, animate, snap 35615 function updateOptions(optionsToUpdate, fireSetEvent) { 35616 // Spectrum is created using the range, snap, direction and step options. 35617 // 'snap' and 'step' can be updated. 35618 // If 'snap' and 'step' are not passed, they should remain unchanged. 35619 var v = valueGet(); 35620 35621 var updateAble = ["margin", "limit", "padding", "range", "animate", "snap", "step", "format"]; 35622 35623 // Only change options that we're actually passed to update. 35624 updateAble.forEach(function(name) { 35625 if (optionsToUpdate[name] !== undefined) { 35626 originalOptions[name] = optionsToUpdate[name]; 35627 } 35628 }); 35629 35630 var newOptions = testOptions(originalOptions); 35631 35632 // Load new options into the slider state 35633 updateAble.forEach(function(name) { 35634 if (optionsToUpdate[name] !== undefined) { 35635 options[name] = newOptions[name]; 35636 } 35637 }); 35638 35639 scope_Spectrum = newOptions.spectrum; 35640 35641 // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677) 35642 options.margin = newOptions.margin; 35643 options.limit = newOptions.limit; 35644 options.padding = newOptions.padding; 35645 35646 // Update pips, removes existing. 35647 if (options.pips) { 35648 pips(options.pips); 35649 } 35650 35651 // Invalidate the current positioning so valueSet forces an update. 35652 scope_Locations = []; 35653 valueSet(optionsToUpdate.start || v, fireSetEvent); 35654 } 35655 35656 // Create the base element, initialize HTML and set classes. 35657 // Add handles and connect elements. 35658 scope_Base = addSlider(scope_Target); 35659 addElements(options.connect, scope_Base); 35660 35661 // Attach user events. 35662 bindSliderEvents(options.events); 35663 35664 // Use the public value method to set the start values. 35665 valueSet(options.start); 35666 35667 // noinspection JSUnusedGlobalSymbols 35668 scope_Self = { 35669 destroy: destroy, 35670 steps: getCurrentStep, 35671 on: bindEvent, 35672 off: removeEvent, 35673 get: valueGet, 35674 set: valueSet, 35675 setHandle: valueSetHandle, 35676 reset: valueReset, 35677 // Exposed for unit testing, don't use this in your application. 35678 __moveHandles: function(a, b, c) { 35679 moveHandles(a, b, scope_Locations, c); 35680 }, 35681 options: originalOptions, // Issue #600, #678 35682 updateOptions: updateOptions, 35683 target: scope_Target, // Issue #597 35684 removePips: removePips, 35685 pips: pips // Issue #594 35686 }; 35687 35688 if (options.pips) { 35689 pips(options.pips); 35690 } 35691 35692 if (options.tooltips) { 35693 tooltips(); 35694 } 35695 35696 aria(); 35697 35698 return scope_Self; 35699 } 35700 35701 // Run the standard initializer 35702 function initialize(target, originalOptions) { 35703 if (!target || !target.nodeName) { 35704 throw new Error("noUiSlider (" + VERSION + "): create requires a single element, got: " + target); 35705 } 35706 35707 // Throw an error if the slider was already initialized. 35708 if (target.noUiSlider) { 35709 throw new Error("noUiSlider (" + VERSION + "): Slider was already initialized."); 35710 } 35711 35712 // Test the options and create the slider environment; 35713 var options = testOptions(originalOptions, target); 35714 var api = scope(target, options, originalOptions); 35715 35716 target.noUiSlider = api; 35717 35718 return api; 35719 } 35720 35721 // Use an object instead of a function for future expandability; 35722 return { 35723 // Exposed for unit testing, don't use this in your application.
35724 __spectrum: Spectrum, 35725 version: VERSION, 35726 create: initialize 35727 }; 35728}); 35729
vendor: 89,992 bytes, lines 35730-39177
35730/** 35731 * Owl Carousel v2.3.4 35732 * Copyright 2013-2018 David Deutsch 35733 * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE 35734 */ 35735/** 35736 * Owl carousel 35737 * @version 2.3.4 35738 * @author Bartosz Wojciechowski 35739 * @author David Deutsch 35740 * @license The MIT License (MIT) 35741 * @todo Lazy Load Icon 35742 * @todo prevent animationend bubling 35743 * @todo itemsScaleUp 35744 * @todo Test Zepto 35745 * @todo stagePadding calculate wrong active classes 35746 */ 35747;(function($, window, document, undefined) { 35748 35749 /** 35750 * Creates a carousel. 35751 * @class The Owl Carousel. 35752 * @public 35753 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 35754 * @param {Object} [options] - The options 35755 */ 35756 function Owl(element, options) { 35757 35758 /** 35759 * Current settings for the carousel. 35760 * @public 35761 */ 35762 this.settings = null; 35763 35764 /** 35765 * Current options set by the caller including defaults. 35766 * @public 35767 */ 35768 this.options = $.extend({}, Owl.Defaults, options); 35769 35770 /** 35771 * Plugin element. 35772 * @public 35773 */ 35774 this.$element = $(element); 35775 35776 /** 35777 * Proxied event handlers. 35778 * @protected 35779 */ 35780 this._handlers = {}; 35781 35782 /** 35783 * References to the running plugins of this carousel. 35784 * @protected 35785 */ 35786 this._plugins = {}; 35787 35788 /** 35789 * Currently suppressed events to prevent them from being retriggered. 35790 * @protected 35791 */ 35792 this._supress = {}; 35793 35794 /** 35795 * Absolute current position. 35796 * @protected 35797 */ 35798 this._current = null; 35799 35800 /** 35801 * Animation speed in milliseconds. 35802 * @protected 35803 */ 35804 this._speed = null; 35805 35806 /** 35807 * Coordinates of all items in pixel. 35808 * @todo The name of this member is missleading. 35809 * @protected 35810 */ 35811 this._coordinates = []; 35812 35813 /** 35814 * Current breakpoint. 35815 * @todo Real media queries would be nice. 35816 * @protected 35817 */ 35818 this._breakpoint = null; 35819 35820 /** 35821 * Current width of the plugin element. 35822 */ 35823 this._width = null; 35824 35825 /** 35826 * All real items. 35827 * @protected 35828 */ 35829 this._items = []; 35830 35831 /** 35832 * All cloned items. 35833 * @protected 35834 */ 35835 this._clones = []; 35836 35837 /** 35838 * Merge values of all items. 35839 * @todo Maybe this could be part of a plugin. 35840 * @protected 35841 */ 35842 this._mergers = []; 35843 35844 /** 35845 * Widths of all items. 35846 */ 35847 this._widths = []; 35848 35849 /** 35850 * Invalidated parts within the update process. 35851 * @protected 35852 */ 35853 this._invalidated = {}; 35854 35855 /** 35856 * Ordered list of workers for the update process. 35857 * @protected 35858 */ 35859 this._pipe = []; 35860 35861 /** 35862 * Current state information for the drag operation. 35863 * @todo #261 35864 * @protected 35865 */ 35866 this._drag = { 35867 time: null, 35868 target: null, 35869 pointer: null, 35870 stage: { 35871 start: null, 35872 current: null 35873 }, 35874 direction: null 35875 }; 35876 35877 /** 35878 * Current state information and their tags. 35879 * @type {Object} 35880 * @protected 35881 */ 35882 this._states = { 35883 current: {}, 35884 tags: { 35885 'initializing': [ 'busy' ], 35886 'animating': [ 'busy' ], 35887 'dragging': [ 'interacting' ] 35888 } 35889 }; 35890 35891 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 35892 this._handlers[handler] = $.proxy(this[handler], this); 35893 }, this)); 35894 35895 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 35896 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 35897 = new plugin(this); 35898 }, this)); 35899 35900 $.each(Owl.Workers, $.proxy(function(priority, worker) { 35901 this._pipe.push({ 35902 'filter': worker.filter, 35903 'run': $.proxy(worker.run, this) 35904 }); 35905 }, this)); 35906 35907 this.setup(); 35908 this.initialize(); 35909 } 35910 35911 /** 35912 * Default options for the carousel. 35913 * @public 35914 */ 35915 Owl.Defaults = { 35916 items: 3, 35917 loop: false, 35918 center: false, 35919 rewind: false, 35920 checkVisibility: true, 35921 35922 mouseDrag: true, 35923 touchDrag: true, 35924 pullDrag: true, 35925 freeDrag: false, 35926 35927 margin: 0, 35928 stagePadding: 0, 35929 35930 merge: false, 35931 mergeFit: true, 35932 autoWidth: false, 35933 35934 startPosition: 0, 35935 rtl: false, 35936 35937 smartSpeed: 250, 35938 fluidSpeed: false, 35939 dragEndSpeed: false, 35940 35941 responsive: {}, 35942 responsiveRefreshRate: 200, 35943 responsiveBaseElement: window, 35944 35945 fallbackEasing: 'swing', 35946 slideTransition: '', 35947 35948 info: false, 35949 35950 nestedItemSelector: false, 35951 itemElement: 'div', 35952 stageElement: 'div', 35953 35954 refreshClass: 'owl-refresh', 35955 loadedClass: 'owl-loaded', 35956 loadingClass: 'owl-loading', 35957 rtlClass: 'owl-rtl', 35958 responsiveClass: 'owl-responsive', 35959 dragClass: 'owl-drag', 35960 itemClass: 'owl-item', 35961 stageClass: 'owl-stage', 35962 stageOuterClass: 'owl-stage-outer', 35963 grabClass: 'owl-grab' 35964 }; 35965 35966 /** 35967 * Enumeration for width. 35968 * @public 35969 * @readonly 35970 * @enum {String} 35971 */ 35972 Owl.Width = { 35973 Default: 'default', 35974 Inner: 'inner', 35975 Outer: 'outer' 35976 }; 35977 35978 /** 35979 * Enumeration for types. 35980 * @public 35981 * @readonly 35982 * @enum {String} 35983 */ 35984 Owl.Type = { 35985 Event: 'event', 35986 State: 'state' 35987 }; 35988 35989 /** 35990 * Contains all registered plugins. 35991 * @public 35992 */ 35993 Owl.Plugins = {}; 35994 35995 /** 35996 * List of workers involved in the update process. 35997 */ 35998 Owl.Workers = [ { 35999 filter: [ 'width', 'settings' ], 36000 run: function() { 36001 this._width = this.$element.width(); 36002 } 36003 }, { 36004 filter: [ 'width', 'items', 'settings' ], 36005 run: function(cache) { 36006 cache.current = this._items && this._items[this.relative(this._current)]; 36007 } 36008 }, { 36009 filter: [ 'items', 'settings' ], 36010 run: function() { 36011 this.$stage.children('.cloned').remove(); 36012 } 36013 }, { 36014 filter: [ 'width', 'items', 'settings' ], 36015 run: function(cache) { 36016 var margin = this.settings.margin || '', 36017 grid = !this.settings.autoWidth, 36018 rtl = this.settings.rtl, 36019 css = { 36020 'width': 'auto', 36021 'margin-left': rtl ? margin : '', 36022 'margin-right': rtl ? '' : margin 36023 }; 36024 36025 !grid && this.$stage.children().css(css); 36026 36027 cache.css = css; 36028 } 36029 }, { 36030 filter: [ 'width', 'items', 'settings' ], 36031 run: function(cache) { 36032 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 36033 merge = null, 36034 iterator = this._items.length, 36035 grid = !this.settings.autoWidth, 36036 widths = []; 36037 36038 cache.items = { 36039 merge: false, 36040 width: width 36041 }; 36042 36043 while (iterator--) { 36044 merge = this._mergers[iterator]; 36045 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 36046 36047 cache.items.merge = merge > 1 || cache.items.merge; 36048 36049 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 36050 } 36051 36052 this._widths = widths; 36053 } 36054 }, { 36055 filter: [ 'items', 'settings' ], 36056 run: function() { 36057 var clones = [], 36058 items = this._items, 36059 settings = this.settings, 36060 // TODO: Should be computed from number of min width items in stage 36061 view = Math.max(settings.items * 2, 4), 36062 size = Math.ceil(items.length / 2) * 2, 36063 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 36064 append = '', 36065 prepend = ''; 36066 36067 repeat /= 2; 36068 36069 while (repeat > 0) { 36070 // Switch to only using appended clones 36071 clones.push(this.normalize(clones.length / 2, true)); 36072 append = append + items[clones[clones.length - 1]][0].outerHTML; 36073 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 36074 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 36075 repeat -= 1; 36076 } 36077 36078 this._clones = clones; 36079 36080 $(append).addClass('cloned').appendTo(this.$stage); 36081 $(prepend).addClass('cloned').prependTo(this.$stage); 36082 } 36083 }, { 36084 filter: [ 'width', 'items', 'settings' ], 36085 run: function() { 36086 var rtl = this.settings.rtl ? 1 : -1, 36087 size = this._clones.length + this._items.length, 36088 iterator = -1, 36089 previous = 0, 36090 current = 0, 36091 coordinates = []; 36092 36093 while (++iterator < size) { 36094 previous = coordinates[iterator - 1] || 0; 36095 current = this._widths[this.relative(iterator)] + this.settings.margin; 36096 coordinates.push(previous + current * rtl); 36097 } 36098 36099 this._coordinates = coordinates; 36100 } 36101 }, { 36102 filter: [ 'width', 'items', 'settings' ], 36103 run: function() { 36104 var padding = this.settings.stagePadding, 36105 coordinates = this._coordinates, 36106 css = { 36107 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 36108 'padding-left': padding || '', 36109 'padding-right': padding || '' 36110 }; 36111 36112 this.$stage.css(css); 36113 } 36114 }, { 36115 filter: [ 'width', 'items', 'settings' ], 36116 run: function(cache) { 36117 var iterator = this._coordinates.length, 36118 grid = !this.settings.autoWidth, 36119 items = this.$stage.children(); 36120 36121 if (grid && cache.items.merge) { 36122 while (iterator--) { 36123 cache.css.width = this._widths[this.relative(iterator)]; 36124 items.eq(iterator).css(cache.css); 36125 } 36126 } else if (grid) { 36127 cache.css.width = cache.items.width; 36128 items.css(cache.css); 36129 } 36130 } 36131 }, { 36132 filter: [ 'items' ], 36133 run: function() { 36134 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 36135 } 36136 }, { 36137 filter: [ 'width', 'items', 'settings' ], 36138 run: function(cache) { 36139 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 36140 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 36141 this.reset(cache.current); 36142 } 36143 }, { 36144 filter: [ 'position' ], 36145 run: function() { 36146 this.animate(this.coordinates(this._current)); 36147 } 36148 }, { 36149 filter: [ 'width', 'position', 'items', 'settings' ], 36150 run: function() { 36151 var rtl = this.settings.rtl ? 1 : -1, 36152 padding = this.settings.stagePadding * 2, 36153 begin = this.coordinates(this.current()) + padding, 36154 end = begin + this.width() * rtl, 36155 inner, outer, matches = [], i, n; 36156 36157 for (i = 0, n = this._coordinates.length; i < n; i++) { 36158 inner = this._coordinates[i - 1] || 0; 36159 outer = Math.abs(this._coordinates[i]) + padding * rtl; 36160 36161 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 36162 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 36163 matches.push(i); 36164 } 36165 } 36166 36167 this.$stage.children('.active').removeClass('active'); 36168 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 36169 36170 this.$stage.children('.center').removeClass('center'); 36171 if (this.settings.center) { 36172 this.$stage.children().eq(this.current()).addClass('center'); 36173 } 36174 } 36175 } ]; 36176 36177 /** 36178 * Create the stage DOM element 36179 */ 36180 Owl.prototype.initializeStage = function() { 36181 this.$stage = this.$element.find('.' + this.settings.stageClass); 36182 36183 // if the stage is already in the DOM, grab it and skip stage initialization 36184 if (this.$stage.length) { 36185 return; 36186 } 36187 36188 this.$element.addClass(this.options.loadingClass); 36189 36190 // create stage 36191 this.$stage = $('<' + this.settings.stageElement + '>', { 36192 "class": this.settings.stageClass 36193 }).wrap( $( '<div/>', { 36194 "class": this.settings.stageOuterClass 36195 })); 36196 36197 // append stage 36198 this.$element.append(this.$stage.parent()); 36199 }; 36200 36201 /** 36202 * Create item DOM elements 36203 */ 36204 Owl.prototype.initializeItems = function() { 36205 var $items = this.$element.find('.owl-item'); 36206 36207 // if the items are already in the DOM, grab them and skip item initialization 36208 if ($items.length) { 36209 this._items = $items.get().map(function(item) { 36210 return $(item); 36211 }); 36212 36213 this._mergers = this._items.map(function() { 36214 return 1; 36215 }); 36216 36217 this.refresh(); 36218 36219 return; 36220 } 36221 36222 // append content 36223 this.replace(this.$element.children().not(this.$stage.parent())); 36224 36225 // check visibility 36226 if (this.isVisible()) { 36227 // update view 36228 this.refresh(); 36229 } else { 36230 // invalidate width 36231 this.invalidate('width'); 36232 } 36233 36234 this.$element 36235 .removeClass(this.options.loadingClass) 36236 .addClass(this.options.loadedClass); 36237 }; 36238 36239 /** 36240 * Initializes the carousel. 36241 * @protected 36242 */ 36243 Owl.prototype.initialize = function() { 36244 this.enter('initializing'); 36245 this.trigger('initialize'); 36246 36247 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 36248 36249 if (this.settings.autoWidth && !this.is('pre-loading')) { 36250 var imgs, nestedSelector, width; 36251 imgs = this.$element.find('img'); 36252 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 36253 width = this.$element.children(nestedSelector).width(); 36254 36255 if (imgs.length && width <= 0) { 36256 this.preloadAutoWidthImages(imgs); 36257 } 36258 } 36259 36260 this.initializeStage(); 36261 this.initializeItems(); 36262 36263 // register event handlers 36264 this.registerEventHandlers(); 36265 36266 this.leave('initializing'); 36267 this.trigger('initialized'); 36268 }; 36269 36270 /** 36271 * @returns {Boolean} visibility of $element 36272 * if you know the carousel will always be visible you can set `checkVisibility` to `false` to 36273 * prevent the expensive browser layout forced reflow the $element.is(':visible') does 36274 */ 36275 Owl.prototype.isVisible = function() { 36276 return this.settings.checkVisibility 36277 ? this.$element.is(':visible') 36278 : true; 36279 }; 36280 36281 /** 36282 * Setups the current settings. 36283 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 36284 * @todo Support for media queries by using `matchMedia` would be nice. 36285 * @public 36286 */ 36287 Owl.prototype.setup = function() { 36288 var viewport = this.viewport(), 36289 overwrites = this.options.responsive, 36290 match = -1, 36291 settings = null; 36292 36293 if (!overwrites) { 36294 settings = $.extend({}, this.options); 36295 } else { 36296 $.each(overwrites, function(breakpoint) { 36297 if (breakpoint <= viewport && breakpoint > match) { 36298 match = Number(breakpoint); 36299 } 36300 }); 36301 36302 settings = $.extend({}, this.options, overwrites[match]); 36303 if (typeof settings.stagePadding === 'function') { 36304 settings.stagePadding = settings.stagePadding(); 36305 } 36306 delete settings.responsive; 36307 36308 // responsive class 36309 if (settings.responsiveClass) { 36310 this.$element.attr('class', 36311 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 36312 ); 36313 } 36314 } 36315 36316 this.trigger('change', { property: { name: 'settings', value: settings } }); 36317 this._breakpoint = match; 36318 this.settings = settings; 36319 this.invalidate('settings'); 36320 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 36321 }; 36322 36323 /** 36324 * Updates option logic if necessery. 36325 * @protected 36326 */ 36327 Owl.prototype.optionsLogic = function() { 36328 if (this.settings.autoWidth) { 36329 this.settings.stagePadding = false; 36330 this.settings.merge = false; 36331 } 36332 }; 36333 36334 /** 36335 * Prepares an item before add. 36336 * @todo Rename event parameter `content` to `item`. 36337 * @protected 36338 * @returns {jQuery|HTMLElement} - The item container. 36339 */ 36340 Owl.prototype.prepare = function(item) { 36341 var event = this.trigger('prepare', { content: item }); 36342 36343 if (!event.data) { 36344 event.data = $('<' + this.settings.itemElement + '/>') 36345 .addClass(this.options.itemClass).append(item) 36346 } 36347 36348 this.trigger('prepared', { content: event.data }); 36349 36350 return event.data; 36351 }; 36352 36353 /** 36354 * Updates the view. 36355 * @public 36356 */ 36357 Owl.prototype.update = function() { 36358 var i = 0, 36359 n = this._pipe.length, 36360 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 36361 cache = {}; 36362 36363 while (i < n) { 36364 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 36365 this._pipe[i].run(cache); 36366 } 36367 i++; 36368 } 36369 36370 this._invalidated = {}; 36371 36372 !this.is('valid') && this.enter('valid'); 36373 }; 36374 36375 /** 36376 * Gets the width of the view. 36377 * @public 36378 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 36379 * @returns {Number} - The width of the view in pixel. 36380 */ 36381 Owl.prototype.width = function(dimension) { 36382 dimension = dimension || Owl.Width.Default; 36383 switch (dimension) { 36384 case Owl.Width.Inner: 36385 case Owl.Width.Outer: 36386 return this._width; 36387 default: 36388 return this._width - this.settings.stagePadding * 2 + this.settings.margin; 36389 } 36390 }; 36391 36392 /** 36393 * Refreshes the carousel primarily for adaptive purposes. 36394 * @public 36395 */ 36396 Owl.prototype.refresh = function() { 36397 this.enter('refreshing'); 36398 this.trigger('refresh'); 36399 36400 this.setup(); 36401 36402 this.optionsLogic(); 36403 36404 this.$element.addClass(this.options.refreshClass); 36405 36406 this.update(); 36407 36408 this.$element.removeClass(this.options.refreshClass); 36409 36410 this.leave('refreshing'); 36411 this.trigger('refreshed'); 36412 }; 36413 36414 /** 36415 * Checks window `resize` event. 36416 * @protected 36417 */ 36418 Owl.prototype.onThrottledResize = function() { 36419 window.clearTimeout(this.resizeTimer); 36420 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 36421 }; 36422 36423 /** 36424 * Checks window `resize` event. 36425 * @protected 36426 */ 36427 Owl.prototype.onResize = function() { 36428 if (!this._items.length) { 36429 return false; 36430 } 36431 36432 if (this._width === this.$element.width()) { 36433 return false; 36434 } 36435 36436 if (!this.isVisible()) { 36437 return false; 36438 } 36439 36440 this.enter('resizing'); 36441 36442 if (this.trigger('resize').isDefaultPrevented()) { 36443 this.leave('resizing'); 36444 return false; 36445 } 36446 36447 this.invalidate('width'); 36448 36449 this.refresh(); 36450 36451 this.leave('resizing'); 36452 this.trigger('resized'); 36453 }; 36454 36455 /** 36456 * Registers event handlers. 36457 * @todo Check `msPointerEnabled` 36458 * @todo #261 36459 * @protected 36460 */ 36461 Owl.prototype.registerEventHandlers = function() { 36462 if ($.support.transition) { 36463 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 36464 } 36465 36466 if (this.settings.responsive !== false) { 36467 this.on(window, 'resize', this._handlers.onThrottledResize); 36468 } 36469 36470 if (this.settings.mouseDrag) { 36471 this.$element.addClass(this.options.dragClass); 36472 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 36473 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 36474 } 36475 36476 if (this.settings.touchDrag){ 36477 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 36478 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 36479 } 36480 }; 36481 36482 /** 36483 * Handles `touchstart` and `mousedown` events. 36484 * @todo Horizontal swipe threshold as option 36485 * @todo #261 36486 * @protected 36487 * @param {Event} event - The event arguments. 36488 */ 36489 Owl.prototype.onDragStart = function(event) { 36490 var stage = null; 36491 36492 if (event.which === 3) { 36493 return; 36494 } 36495 36496 if ($.support.transform) { 36497 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 36498 stage = { 36499 x: stage[stage.length === 16 ? 12 : 4], 36500 y: stage[stage.length === 16 ? 13 : 5] 36501 }; 36502 } else { 36503 stage = this.$stage.position(); 36504 stage = { 36505 x: this.settings.rtl ? 36506 stage.left + this.$stage.width() - this.width() + this.settings.margin : 36507 stage.left, 36508 y: stage.top 36509 }; 36510 } 36511 36512 if (this.is('animating')) { 36513 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 36514 this.invalidate('position'); 36515 } 36516 36517 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 36518 36519 this.speed(0); 36520 36521 this._drag.time = new Date().getTime(); 36522 this._drag.target = $(event.target); 36523 this._drag.stage.start = stage; 36524 this._drag.stage.current = stage; 36525 this._drag.pointer = this.pointer(event); 36526 36527 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 36528 36529 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 36530 var delta = this.difference(this._drag.pointer, this.pointer(event)); 36531 36532 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 36533 36534 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 36535 return; 36536 } 36537 36538 event.preventDefault(); 36539 36540 this.enter('dragging'); 36541 this.trigger('drag'); 36542 }, this)); 36543 }; 36544 36545 /** 36546 * Handles the `touchmove` and `mousemove` events. 36547 * @todo #261 36548 * @protected 36549 * @param {Event} event - The event arguments. 36550 */ 36551 Owl.prototype.onDragMove = function(event) { 36552 var minimum = null, 36553 maximum = null, 36554 pull = null, 36555 delta = this.difference(this._drag.pointer, this.pointer(event)), 36556 stage = this.difference(this._drag.stage.start, delta); 36557 36558 if (!this.is('dragging')) { 36559 return; 36560 } 36561 36562 event.preventDefault(); 36563 36564 if (this.settings.loop) { 36565 minimum = this.coordinates(this.minimum()); 36566 maximum = this.coordinates(this.maximum() + 1) - minimum; 36567 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 36568 } else { 36569 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 36570 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 36571 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 36572 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 36573 } 36574 36575 this._drag.stage.current = stage; 36576 36577 this.animate(stage.x); 36578 }; 36579 36580 /** 36581 * Handles the `touchend` and `mouseup` events. 36582 * @todo #261 36583 * @todo Threshold for click event 36584 * @protected 36585 * @param {Event} event - The event arguments. 36586 */ 36587 Owl.prototype.onDragEnd = function(event) { 36588 var delta = this.difference(this._drag.pointer, this.pointer(event)), 36589 stage = this._drag.stage.current, 36590 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 36591 36592 $(document).off('.owl.core'); 36593 36594 this.$element.removeClass(this.options.grabClass); 36595 36596 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 36597 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 36598 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 36599 this.invalidate('position'); 36600 this.update(); 36601 36602 this._drag.direction = direction; 36603 36604 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 36605 this._drag.target.one('click.owl.core', function() { return false; }); 36606 } 36607 } 36608 36609 if (!this.is('dragging')) { 36610 return; 36611 } 36612 36613 this.leave('dragging'); 36614 this.trigger('dragged'); 36615 }; 36616 36617 /** 36618 * Gets absolute position of the closest item for a coordinate. 36619 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 36620 * @protected 36621 * @param {Number} coordinate - The coordinate in pixel. 36622 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 36623 * @return {Number} - The absolute position of the closest item. 36624 */ 36625 Owl.prototype.closest = function(coordinate, direction) { 36626 var position = -1, 36627 pull = 30, 36628 width = this.width(), 36629 coordinates = this.coordinates(); 36630 36631 if (!this.settings.freeDrag) { 36632 // check closest item 36633 $.each(coordinates, $.proxy(function(index, value) { 36634 // on a left pull, check on current index 36635 if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) { 36636 position = index; 36637 // on a right pull, check on previous index 36638 // to do so, subtract width from value and set position = index + 1 36639 } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) { 36640 position = index + 1; 36641 } else if (this.op(coordinate, '<', value) 36642 && this.op(coordinate, '>', coordinates[index + 1] !== undefined ? coordinates[index + 1] : value - width)) { 36643 position = direction === 'left' ? index + 1 : index; 36644 } 36645 return position === -1; 36646 }, this)); 36647 } 36648 36649 if (!this.settings.loop) { 36650 // non loop boundries 36651 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 36652 position = coordinate = this.minimum(); 36653 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 36654 position = coordinate = this.maximum(); 36655 } 36656 } 36657 36658 return position; 36659 }; 36660 36661 /** 36662 * Animates the stage. 36663 * @todo #270 36664 * @public 36665 * @param {Number} coordinate - The coordinate in pixels. 36666 */ 36667 Owl.prototype.animate = function(coordinate) { 36668 var animate = this.speed() > 0; 36669 36670 this.is('animating') && this.onTransitionEnd(); 36671 36672 if (animate) { 36673 this.enter('animating'); 36674 this.trigger('translate'); 36675 } 36676 36677 if ($.support.transform3d && $.support.transition) { 36678 this.$stage.css({ 36679 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 36680 transition: (this.speed() / 1000) + 's' + ( 36681 this.settings.slideTransition ? ' ' + this.settings.slideTransition : '' 36682 ) 36683 }); 36684 } else if (animate) { 36685 this.$stage.animate({ 36686 left: coordinate + 'px' 36687 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 36688 } else { 36689 this.$stage.css({ 36690 left: coordinate + 'px' 36691 }); 36692 } 36693 }; 36694 36695 /** 36696 * Checks whether the carousel is in a specific state or not. 36697 * @param {String} state - The state to check. 36698 * @returns {Boolean} - The flag which indicates if the carousel is busy. 36699 */ 36700 Owl.prototype.is = function(state) { 36701 return this._states.current[state] && this._states.current[state] > 0; 36702 }; 36703 36704 /** 36705 * Sets the absolute position of the current item. 36706 * @public 36707 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 36708 * @returns {Number} - The absolute position of the current item. 36709 */ 36710 Owl.prototype.current = function(position) { 36711 if (position === undefined) { 36712 return this._current; 36713 } 36714 36715 if (this._items.length === 0) { 36716 return undefined; 36717 } 36718 36719 position = this.normalize(position); 36720 36721 if (this._current !== position) { 36722 var event = this.trigger('change', { property: { name: 'position', value: position } }); 36723 36724 if (event.data !== undefined) { 36725 position = this.normalize(event.data); 36726 } 36727 36728 this._current = position; 36729 36730 this.invalidate('position'); 36731 36732 this.trigger('changed', { property: { name: 'position', value: this._current } }); 36733 } 36734 36735 return this._current; 36736 }; 36737 36738 /** 36739 * Invalidates the given part of the update routine. 36740 * @param {String} [part] - The part to invalidate. 36741 * @returns {Array.<String>} - The invalidated parts. 36742 */ 36743 Owl.prototype.invalidate = function(part) { 36744 if ($.type(part) === 'string') { 36745 this._invalidated[part] = true; 36746 this.is('valid') && this.leave('valid'); 36747 } 36748 return $.map(this._invalidated, function(v, i) { return i }); 36749 }; 36750 36751 /** 36752 * Resets the absolute position of the current item. 36753 * @public 36754 * @param {Number} position - The absolute position of the new item. 36755 */ 36756 Owl.prototype.reset = function(position) { 36757 position = this.normalize(position); 36758 36759 if (position === undefined) { 36760 return; 36761 } 36762 36763 this._speed = 0; 36764 this._current = position; 36765 36766 this.suppress([ 'translate', 'translated' ]); 36767 36768 this.animate(this.coordinates(position)); 36769 36770 this.release([ 'translate', 'translated' ]); 36771 }; 36772 36773 /** 36774 * Normalizes an absolute or a relative position of an item. 36775 * @public 36776 * @param {Number} position - The absolute or relative position to normalize. 36777 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 36778 * @returns {Number} - The normalized position. 36779 */ 36780 Owl.prototype.normalize = function(position, relative) { 36781 var n = this._items.length, 36782 m = relative ? 0 : this._clones.length; 36783 36784 if (!this.isNumeric(position) || n < 1) { 36785 position = undefined; 36786 } else if (position < 0 || position >= n + m) { 36787 position = ((position - m / 2) % n + n) % n + m / 2; 36788 } 36789 36790 return position; 36791 }; 36792 36793 /** 36794 * Converts an absolute position of an item into a relative one. 36795 * @public 36796 * @param {Number} position - The absolute position to convert. 36797 * @returns {Number} - The converted position. 36798 */ 36799 Owl.prototype.relative = function(position) { 36800 position -= this._clones.length / 2; 36801 return this.normalize(position, true); 36802 }; 36803 36804 /** 36805 * Gets the maximum position for the current item. 36806 * @public 36807 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36808 * @returns {Number} 36809 */ 36810 Owl.prototype.maximum = function(relative) { 36811 var settings = this.settings, 36812 maximum = this._coordinates.length, 36813 iterator, 36814 reciprocalItemsWidth, 36815 elementWidth; 36816 36817 if (settings.loop) { 36818 maximum = this._clones.length / 2 + this._items.length - 1; 36819 } else if (settings.autoWidth || settings.merge) { 36820 iterator = this._items.length; 36821 if (iterator) { 36822 reciprocalItemsWidth = this._items[--iterator].width(); 36823 elementWidth = this.$element.width(); 36824 while (iterator--) { 36825 reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin; 36826 if (reciprocalItemsWidth > elementWidth) { 36827 break; 36828 } 36829 } 36830 } 36831 maximum = iterator + 1; 36832 } else if (settings.center) { 36833 maximum = this._items.length - 1; 36834 } else { 36835 maximum = this._items.length - settings.items; 36836 } 36837 36838 if (relative) { 36839 maximum -= this._clones.length / 2; 36840 } 36841 36842 return Math.max(maximum, 0); 36843 }; 36844 36845 /** 36846 * Gets the minimum position for the current item. 36847 * @public 36848 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 36849 * @returns {Number} 36850 */ 36851 Owl.prototype.minimum = function(relative) { 36852 return relative ? 0 : this._clones.length / 2; 36853 }; 36854 36855 /** 36856 * Gets an item at the specified relative position. 36857 * @public 36858 * @param {Number} [position] - The relative position of the item. 36859 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36860 */ 36861 Owl.prototype.items = function(position) { 36862 if (position === undefined) { 36863 return this._items.slice(); 36864 } 36865 36866 position = this.normalize(position, true); 36867 return this._items[position]; 36868 }; 36869 36870 /** 36871 * Gets an item at the specified relative position. 36872 * @public 36873 * @param {Number} [position] - The relative position of the item. 36874 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 36875 */ 36876 Owl.prototype.mergers = function(position) { 36877 if (position === undefined) { 36878 return this._mergers.slice(); 36879 } 36880 36881 position = this.normalize(position, true); 36882 return this._mergers[position]; 36883 }; 36884 36885 /** 36886 * Gets the absolute positions of clones for an item. 36887 * @public 36888 * @param {Number} [position] - The relative position of the item. 36889 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 36890 */ 36891 Owl.prototype.clones = function(position) { 36892 var odd = this._clones.length / 2, 36893 even = odd + this._items.length, 36894 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 36895 36896 if (position === undefined) { 36897 return $.map(this._clones, function(v, i) { return map(i) }); 36898 } 36899 36900 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 36901 }; 36902 36903 /** 36904 * Sets the current animation speed. 36905 * @public 36906 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 36907 * @returns {Number} - The current animation speed in milliseconds. 36908 */ 36909 Owl.prototype.speed = function(speed) { 36910 if (speed !== undefined) { 36911 this._speed = speed; 36912 } 36913 36914 return this._speed; 36915 }; 36916 36917 /** 36918 * Gets the coordinate of an item. 36919 * @todo The name of this method is missleanding. 36920 * @public 36921 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 36922 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 36923 */ 36924 Owl.prototype.coordinates = function(position) { 36925 var multiplier = 1, 36926 newPosition = position - 1, 36927 coordinate; 36928 36929 if (position === undefined) { 36930 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 36931 return this.coordinates(index); 36932 }, this)); 36933 } 36934 36935 if (this.settings.center) { 36936 if (this.settings.rtl) { 36937 multiplier = -1; 36938 newPosition = position + 1; 36939 } 36940 36941 coordinate = this._coordinates[position]; 36942 coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier; 36943 } else { 36944 coordinate = this._coordinates[newPosition] || 0; 36945 } 36946 36947 coordinate = Math.ceil(coordinate); 36948 36949 return coordinate; 36950 }; 36951 36952 /** 36953 * Calculates the speed for a translation. 36954 * @protected 36955 * @param {Number} from - The absolute position of the start item. 36956 * @param {Number} to - The absolute position of the target item. 36957 * @param {Number} [factor=undefined] - The time factor in milliseconds. 36958 * @returns {Number} - The time in milliseconds for the translation. 36959 */ 36960 Owl.prototype.duration = function(from, to, factor) { 36961 if (factor === 0) { 36962 return 0; 36963 } 36964 36965 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 36966 }; 36967 36968 /** 36969 * Slides to the specified item. 36970 * @public 36971 * @param {Number} position - The position of the item. 36972 * @param {Number} [speed] - The time in milliseconds for the transition. 36973 */ 36974 Owl.prototype.to = function(position, speed) { 36975 var current = this.current(), 36976 revert = null, 36977 distance = position - this.relative(current), 36978 direction = (distance > 0) - (distance < 0), 36979 items = this._items.length, 36980 minimum = this.minimum(), 36981 maximum = this.maximum(); 36982 36983 if (this.settings.loop) { 36984 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 36985 distance += direction * -1 * items; 36986 } 36987 36988 position = current + distance; 36989 revert = ((position - minimum) % items + items) % items + minimum; 36990 36991 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 36992 current = revert - distance; 36993 position = revert; 36994 this.reset(current); 36995 } 36996 } else if (this.settings.rewind) { 36997 maximum += 1; 36998 position = (position % maximum + maximum) % maximum; 36999 } else { 37000 position = Math.max(minimum, Math.min(maximum, position)); 37001 } 37002 37003 this.speed(this.duration(current, position, speed)); 37004 this.current(position); 37005 37006 if (this.isVisible()) { 37007 this.update(); 37008 } 37009 }; 37010 37011 /** 37012 * Slides to the next item. 37013 * @public 37014 * @param {Number} [speed] - The time in milliseconds for the transition. 37015 */ 37016 Owl.prototype.next = function(speed) { 37017 speed = speed || false; 37018 this.to(this.relative(this.current()) + 1, speed); 37019 }; 37020 37021 /** 37022 * Slides to the previous item. 37023 * @public 37024 * @param {Number} [speed] - The time in milliseconds for the transition. 37025 */ 37026 Owl.prototype.prev = function(speed) { 37027 speed = speed || false; 37028 this.to(this.relative(this.current()) - 1, speed); 37029 }; 37030 37031 /** 37032 * Handles the end of an animation. 37033 * @protected 37034 * @param {Event} event - The event arguments. 37035 */ 37036 Owl.prototype.onTransitionEnd = function(event) { 37037 37038 // if css2 animation then event object is undefined 37039 if (event !== undefined) { 37040 event.stopPropagation(); 37041 37042 // Catch only owl-stage transitionEnd event 37043 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 37044 return false; 37045 } 37046 } 37047 37048 this.leave('animating'); 37049 this.trigger('translated'); 37050 }; 37051 37052 /** 37053 * Gets viewport width. 37054 * @protected 37055 * @return {Number} - The width in pixel. 37056 */ 37057 Owl.prototype.viewport = function() { 37058 var width; 37059 if (this.options.responsiveBaseElement !== window) { 37060 width = $(this.options.responsiveBaseElement).width(); 37061 } else if (window.innerWidth) { 37062 width = window.innerWidth; 37063 } else if (document.documentElement && document.documentElement.clientWidth) { 37064 width = document.documentElement.clientWidth; 37065 } else { 37066 console.warn('Can not detect viewport width.'); 37067 } 37068 return width; 37069 }; 37070 37071 /** 37072 * Replaces the current content. 37073 * @public 37074 * @param {HTMLElement|jQuery|String} content - The new content. 37075 */ 37076 Owl.prototype.replace = function(content) { 37077 this.$stage.empty(); 37078 this._items = []; 37079 37080 if (content) { 37081 content = (content instanceof jQuery) ? content : $(content); 37082 } 37083 37084 if (this.settings.nestedItemSelector) { 37085 content = content.find('.' + this.settings.nestedItemSelector); 37086 } 37087 37088 content.filter(function() { 37089 return this.nodeType === 1; 37090 }).each($.proxy(function(index, item) { 37091 item = this.prepare(item); 37092 this.$stage.append(item); 37093 this._items.push(item); 37094 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 37095 }, this)); 37096 37097 this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 37098 37099 this.invalidate('items'); 37100 }; 37101 37102 /** 37103 * Adds an item. 37104 * @todo Use `item` instead of `content` for the event arguments. 37105 * @public 37106 * @param {HTMLElement|jQuery|String} content - The item content to add. 37107 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 37108 */ 37109 Owl.prototype.add = function(content, position) { 37110 var current = this.relative(this._current); 37111 37112 position = position === undefined ? this._items.length : this.normalize(position, true); 37113 content = content instanceof jQuery ? content : $(content); 37114 37115 this.trigger('add', { content: content, position: position }); 37116 37117 content = this.prepare(content); 37118 37119 if (this._items.length === 0 || position === this._items.length) { 37120 this._items.length === 0 && this.$stage.append(content); 37121 this._items.length !== 0 && this._items[position - 1].after(content); 37122 this._items.push(content); 37123 this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 37124 } else { 37125 this._items[position].before(content); 37126 this._items.splice(position, 0, content); 37127 this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 37128 } 37129 37130 this._items[current] && this.reset(this._items[current].index()); 37131 37132 this.invalidate('items'); 37133 37134 this.trigger('added', { content: content, position: position }); 37135 }; 37136 37137 /** 37138 * Removes an item by its position. 37139 * @todo Use `item` instead of `content` for the event arguments. 37140 * @public 37141 * @param {Number} position - The relative position of the item to remove. 37142 */ 37143 Owl.prototype.remove = function(position) { 37144 position = this.normalize(position, true); 37145 37146 if (position === undefined) { 37147 return; 37148 } 37149 37150 this.trigger('remove', { content: this._items[position], position: position }); 37151 37152 this._items[position].remove(); 37153 this._items.splice(position, 1); 37154 this._mergers.splice(position, 1); 37155 37156 this.invalidate('items'); 37157 37158 this.trigger('removed', { content: null, position: position }); 37159 }; 37160 37161 /** 37162 * Preloads images with auto width. 37163 * @todo Replace by a more generic approach 37164 * @protected 37165 */ 37166 Owl.prototype.preloadAutoWidthImages = function(images) { 37167 images.each($.proxy(function(i, element) { 37168 this.enter('pre-loading'); 37169 element = $(element); 37170 $(new Image()).one('load', $.proxy(function(e) { 37171 element.attr('src', e.target.src); 37172 element.css('opacity', 1); 37173 this.leave('pre-loading'); 37174 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 37175 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 37176 }, this)); 37177 }; 37178 37179 /** 37180 * Destroys the carousel. 37181 * @public 37182 */ 37183 Owl.prototype.destroy = function() { 37184 37185 this.$element.off('.owl.core'); 37186 this.$stage.off('.owl.core'); 37187 $(document).off('.owl.core'); 37188 37189 if (this.settings.responsive !== false) { 37190 window.clearTimeout(this.resizeTimer); 37191 this.off(window, 'resize', this._handlers.onThrottledResize); 37192 } 37193 37194 for (var i in this._plugins) { 37195 this._plugins[i].destroy(); 37196 } 37197 37198 this.$stage.children('.cloned').remove(); 37199 37200 this.$stage.unwrap(); 37201 this.$stage.children().contents().unwrap(); 37202 this.$stage.children().unwrap(); 37203 this.$stage.remove(); 37204 this.$element 37205 .removeClass(this.options.refreshClass) 37206 .removeClass(this.options.loadingClass) 37207 .removeClass(this.options.loadedClass) 37208 .removeClass(this.options.rtlClass) 37209 .removeClass(this.options.dragClass) 37210 .removeClass(this.options.grabClass) 37211 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 37212 .removeData('owl.carousel'); 37213 }; 37214 37215 /** 37216 * Operators to calculate right-to-left and left-to-right. 37217 * @protected 37218 * @param {Number} [a] - The left side operand. 37219 * @param {String} [o] - The operator. 37220 * @param {Number} [b] - The right side operand. 37221 */ 37222 Owl.prototype.op = function(a, o, b) { 37223 var rtl = this.settings.rtl; 37224 switch (o) { 37225 case '<': 37226 return rtl ? a > b : a < b; 37227 case '>': 37228 return rtl ? a < b : a > b; 37229 case '>=': 37230 return rtl ? a <= b : a >= b; 37231 case '<=': 37232 return rtl ? a >= b : a <= b; 37233 default: 37234 break; 37235 } 37236 }; 37237 37238 /** 37239 * Attaches to an internal event. 37240 * @protected 37241 * @param {HTMLElement} element - The event source. 37242 * @param {String} event - The event name. 37243 * @param {Function} listener - The event handler to attach. 37244 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 37245 */ 37246 Owl.prototype.on = function(element, event, listener, capture) { 37247 if (element.addEventListener) { 37248 element.addEventListener(event, listener, capture); 37249 } else if (element.attachEvent) { 37250 element.attachEvent('on' + event, listener); 37251 } 37252 }; 37253 37254 /** 37255 * Detaches from an internal event. 37256 * @protected 37257 * @param {HTMLElement} element - The event source. 37258 * @param {String} event - The event name. 37259 * @param {Function} listener - The attached event handler to detach. 37260 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 37261 */ 37262 Owl.prototype.off = function(element, event, listener, capture) { 37263 if (element.removeEventListener) { 37264 element.removeEventListener(event, listener, capture); 37265 } else if (element.detachEvent) { 37266 element.detachEvent('on' + event, listener); 37267 } 37268 }; 37269 37270 /** 37271 * Triggers a public event. 37272 * @todo Remove `status`, `relatedTarget` should be used instead. 37273 * @protected 37274 * @param {String} name - The event name. 37275 * @param {*} [data=null] - The event data. 37276 * @param {String} [namespace=carousel] - The event namespace. 37277 * @param {String} [state] - The state which is associated with the event. 37278 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 37279 * @returns {Event} - The event arguments. 37280 */ 37281 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 37282 var status = { 37283 item: { count: this._items.length, index: this.current() } 37284 }, handler = $.camelCase( 37285 $.grep([ 'on', name, namespace ], function(v) { return v }) 37286 .join('-').toLowerCase() 37287 ), event = $.Event( 37288 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 37289 $.extend({ relatedTarget: this }, status, data) 37290 ); 37291 37292 if (!this._supress[name]) { 37293 $.each(this._plugins, function(name, plugin) { 37294 if (plugin.onTrigger) { 37295 plugin.onTrigger(event); 37296 } 37297 }); 37298 37299 this.register({ type: Owl.Type.Event, name: name }); 37300 this.$element.trigger(event); 37301 37302 if (this.settings && typeof this.settings[handler] === 'function') { 37303 this.settings[handler].call(this, event); 37304 } 37305 } 37306 37307 return event; 37308 }; 37309 37310 /** 37311 * Enters a state. 37312 * @param name - The state name. 37313 */ 37314 Owl.prototype.enter = function(name) { 37315 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 37316 if (this._states.current[name] === undefined) { 37317 this._states.current[name] = 0; 37318 } 37319 37320 this._states.current[name]++; 37321 }, this)); 37322 }; 37323 37324 /** 37325 * Leaves a state. 37326 * @param name - The state name. 37327 */ 37328 Owl.prototype.leave = function(name) { 37329 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 37330 this._states.current[name]--; 37331 }, this)); 37332 }; 37333 37334 /** 37335 * Registers an event or state. 37336 * @public 37337 * @param {Object} object - The event or state to register. 37338 */ 37339 Owl.prototype.register = function(object) { 37340 if (object.type === Owl.Type.Event) { 37341 if (!$.event.special[object.name]) { 37342 $.event.special[object.name] = {}; 37343 } 37344 37345 if (!$.event.special[object.name].owl) { 37346 var _default = $.event.special[object.name]._default; 37347 $.event.special[object.name]._default = function(e) { 37348 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 37349 return _default.apply(this, arguments); 37350 } 37351 return e.namespace && e.namespace.indexOf('owl') > -1; 37352 }; 37353 $.event.special[object.name].owl = true; 37354 } 37355 } else if (object.type === Owl.Type.State) { 37356 if (!this._states.tags[object.name]) { 37357 this._states.tags[object.name] = object.tags; 37358 } else { 37359 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 37360 } 37361 37362 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 37363 return $.inArray(tag, this._states.tags[object.name]) === i; 37364 }, this)); 37365 } 37366 }; 37367 37368 /** 37369 * Suppresses events. 37370 * @protected 37371 * @param {Array.<String>} events - The events to suppress. 37372 */ 37373 Owl.prototype.suppress = function(events) { 37374 $.each(events, $.proxy(function(index, event) { 37375 this._supress[event] = true; 37376 }, this)); 37377 }; 37378 37379 /** 37380 * Releases suppressed events. 37381 * @protected 37382 * @param {Array.<String>} events - The events to release. 37383 */ 37384 Owl.prototype.release = function(events) { 37385 $.each(events, $.proxy(function(index, event) { 37386 delete this._supress[event]; 37387 }, this)); 37388 }; 37389 37390 /** 37391 * Gets unified pointer coordinates from event. 37392 * @todo #261 37393 * @protected 37394 * @param {Event} - The `mousedown` or `touchstart` event. 37395 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 37396 */ 37397 Owl.prototype.pointer = function(event) { 37398 var result = { x: null, y: null }; 37399 37400 event = event.originalEvent || event || window.event; 37401 37402 event = event.touches && event.touches.length ? 37403 event.touches[0] : event.changedTouches && event.changedTouches.length ? 37404 event.changedTouches[0] : event; 37405 37406 if (event.pageX) { 37407 result.x = event.pageX; 37408 result.y = event.pageY; 37409 } else { 37410 result.x = event.clientX; 37411 result.y = event.clientY; 37412 } 37413 37414 return result; 37415 }; 37416 37417 /** 37418 * Determines if the input is a Number or something that can be coerced to a Number 37419 * @protected 37420 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested 37421 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number 37422 */ 37423 Owl.prototype.isNumeric = function(number) { 37424 return !isNaN(parseFloat(number)); 37425 }; 37426 37427 /** 37428 * Gets the difference of two vectors. 37429 * @todo #261 37430 * @protected 37431 * @param {Object} - The first vector. 37432 * @param {Object} - The second vector. 37433 * @returns {Object} - The difference. 37434 */ 37435 Owl.prototype.difference = function(first, second) { 37436 return { 37437 x: first.x - second.x, 37438 y: first.y - second.y 37439 }; 37440 }; 37441 37442 /** 37443 * The jQuery Plugin for the Owl Carousel 37444 * @todo Navigation plugin `next` and `prev` 37445 * @public 37446 */ 37447 $.fn.owlCarousel = function(option) { 37448 var args = Array.prototype.slice.call(arguments, 1); 37449 37450 return this.each(function() { 37451 var $this = $(this), 37452 data = $this.data('owl.carousel'); 37453 37454 if (!data) { 37455 data = new Owl(this, typeof option == 'object' && option); 37456 $this.data('owl.carousel', data); 37457 37458 $.each([ 37459 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 37460 ], function(i, event) { 37461 data.register({ type: Owl.Type.Event, name: event }); 37462 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 37463 if (e.namespace && e.relatedTarget !== this) { 37464 this.suppress([ event ]); 37465 data[event].apply(this, [].slice.call(arguments, 1)); 37466 this.release([ event ]); 37467 } 37468 }, data)); 37469 }); 37470 } 37471 37472 if (typeof option == 'string' && option.charAt(0) !== '_') { 37473 data[option].apply(data, args); 37474 } 37475 }); 37476 }; 37477 37478 /** 37479 * The constructor for the jQuery Plugin 37480 * @public 37481 */ 37482 $.fn.owlCarousel.Constructor = Owl; 37483 37484})(window.Zepto || window.jQuery, window, document); 37485 37486/** 37487 * AutoRefresh Plugin 37488 * @version 2.3.4 37489 * @author Artus Kolanowski 37490 * @author David Deutsch 37491 * @license The MIT License (MIT) 37492 */ 37493;(function($, window, document, undefined) { 37494 37495 /** 37496 * Creates the auto refresh plugin. 37497 * @class The Auto Refresh Plugin 37498 * @param {Owl} carousel - The Owl Carousel 37499 */ 37500 var AutoRefresh = function(carousel) { 37501 /** 37502 * Reference to the core. 37503 * @protected 37504 * @type {Owl} 37505 */ 37506 this._core = carousel; 37507 37508 /** 37509 * Refresh interval. 37510 * @protected 37511 * @type {number} 37512 */ 37513 this._interval = null; 37514 37515 /** 37516 * Whether the element is currently visible or not. 37517 * @protected 37518 * @type {Boolean} 37519 */ 37520 this._visible = null; 37521 37522 /** 37523 * All event handlers. 37524 * @protected 37525 * @type {Object} 37526 */ 37527 this._handlers = { 37528 'initialized.owl.carousel': $.proxy(function(e) { 37529 if (e.namespace && this._core.settings.autoRefresh) { 37530 this.watch(); 37531 } 37532 }, this) 37533 }; 37534 37535 // set default options 37536 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 37537 37538 // register event handlers 37539 this._core.$element.on(this._handlers); 37540 }; 37541 37542 /** 37543 * Default options. 37544 * @public 37545 */ 37546 AutoRefresh.Defaults = { 37547 autoRefresh: true, 37548 autoRefreshInterval: 500 37549 }; 37550 37551 /** 37552 * Watches the element. 37553 */ 37554 AutoRefresh.prototype.watch = function() { 37555 if (this._interval) { 37556 return; 37557 } 37558 37559 this._visible = this._core.isVisible(); 37560 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 37561 }; 37562 37563 /** 37564 * Refreshes the element. 37565 */ 37566 AutoRefresh.prototype.refresh = function() { 37567 if (this._core.isVisible() === this._visible) { 37568 return; 37569 } 37570 37571 this._visible = !this._visible; 37572 37573 this._core.$element.toggleClass('owl-hidden', !this._visible); 37574 37575 this._visible && (this._core.invalidate('width') && this._core.refresh()); 37576 }; 37577 37578 /** 37579 * Destroys the plugin. 37580 */ 37581 AutoRefresh.prototype.destroy = function() { 37582 var handler, property; 37583 37584 window.clearInterval(this._interval); 37585 37586 for (handler in this._handlers) { 37587 this._core.$element.off(handler, this._handlers[handler]); 37588 } 37589 for (property in Object.getOwnPropertyNames(this)) { 37590 typeof this[property] != 'function' && (this[property] = null); 37591 } 37592 }; 37593 37594 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 37595 37596})(window.Zepto || window.jQuery, window, document); 37597 37598/** 37599 * Lazy Plugin 37600 * @version 2.3.4 37601 * @author Bartosz Wojciechowski 37602 * @author David Deutsch 37603 * @license The MIT License (MIT) 37604 */ 37605;(function($, window, document, undefined) { 37606 37607 /** 37608 * Creates the lazy plugin. 37609 * @class The Lazy Plugin 37610 * @param {Owl} carousel - The Owl Carousel 37611 */ 37612 var Lazy = function(carousel) { 37613 37614 /** 37615 * Reference to the core. 37616 * @protected 37617 * @type {Owl} 37618 */ 37619 this._core = carousel; 37620 37621 /** 37622 * Already loaded items. 37623 * @protected 37624 * @type {Array.<jQuery>} 37625 */ 37626 this._loaded = []; 37627 37628 /** 37629 * Event handlers. 37630 * @protected 37631 * @type {Object} 37632 */ 37633 this._handlers = { 37634 'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) { 37635 if (!e.namespace) { 37636 return; 37637 } 37638 37639 if (!this._core.settings || !this._core.settings.lazyLoad) { 37640 return; 37641 } 37642 37643 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 37644 var settings = this._core.settings, 37645 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 37646 i = ((settings.center && n * -1) || 0), 37647 position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i, 37648 clones = this._core.clones().length, 37649 load = $.proxy(function(i, v) { this.load(v) }, this); 37650 //TODO: Need documentation for this new option 37651 if (settings.lazyLoadEager > 0) { 37652 n += settings.lazyLoadEager; 37653 // If the carousel is looping also preload images that are to the "left" 37654 if (settings.loop) { 37655 position -= settings.lazyLoadEager; 37656 n++; 37657 } 37658 } 37659 37660 while (i++ < n) { 37661 this.load(clones / 2 + this._core.relative(position)); 37662 clones && $.each(this._core.clones(this._core.relative(position)), load); 37663 position++; 37664 } 37665 } 37666 }, this) 37667 }; 37668 37669 // set the default options 37670 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 37671 37672 // register event handler 37673 this._core.$element.on(this._handlers); 37674 }; 37675 37676 /** 37677 * Default options. 37678 * @public 37679 */ 37680 Lazy.Defaults = { 37681 lazyLoad: false, 37682 lazyLoadEager: 0 37683 }; 37684 37685 /** 37686 * Loads all resources of an item at the specified position. 37687 * @param {Number} position - The absolute position of the item. 37688 * @protected 37689 */ 37690 Lazy.prototype.load = function(position) { 37691 var $item = this._core.$stage.children().eq(position), 37692 $elements = $item && $item.find('.owl-lazy'); 37693 37694 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 37695 return; 37696 } 37697 37698 $elements.each($.proxy(function(index, element) { 37699 var $element = $(element), image, 37700 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src') || $element.attr('data-srcset'); 37701 37702 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 37703 37704 if ($element.is('img')) { 37705 $element.one('load.owl.lazy', $.proxy(function() { 37706 $element.css('opacity', 1); 37707 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37708 }, this)).attr('src', url); 37709 } else if ($element.is('source')) { 37710 $element.one('load.owl.lazy', $.proxy(function() { 37711 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37712 }, this)).attr('srcset', url); 37713 } else { 37714 image = new Image(); 37715 image.onload = $.proxy(function() { 37716 $element.css({ 37717 'background-image': 'url("' + url + '")', 37718 'opacity': '1' 37719 }); 37720 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 37721 }, this); 37722 image.src = url; 37723 } 37724 }, this)); 37725 37726 this._loaded.push($item.get(0)); 37727 }; 37728 37729 /** 37730 * Destroys the plugin. 37731 * @public 37732 */ 37733 Lazy.prototype.destroy = function() { 37734 var handler, property; 37735 37736 for (handler in this.handlers) { 37737 this._core.$element.off(handler, this.handlers[handler]); 37738 } 37739 for (property in Object.getOwnPropertyNames(this)) { 37740 typeof this[property] != 'function' && (this[property] = null); 37741 } 37742 }; 37743 37744 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 37745 37746})(window.Zepto || window.jQuery, window, document); 37747 37748/** 37749 * AutoHeight Plugin 37750 * @version 2.3.4 37751 * @author Bartosz Wojciechowski 37752 * @author David Deutsch 37753 * @license The MIT License (MIT) 37754 */ 37755;(function($, window, document, undefined) { 37756 37757 /** 37758 * Creates the auto height plugin. 37759 * @class The Auto Height Plugin 37760 * @param {Owl} carousel - The Owl Carousel 37761 */ 37762 var AutoHeight = function(carousel) { 37763 /** 37764 * Reference to the core. 37765 * @protected 37766 * @type {Owl} 37767 */ 37768 this._core = carousel; 37769 37770 this._previousHeight = null; 37771 37772 /** 37773 * All event handlers. 37774 * @protected 37775 * @type {Object} 37776 */ 37777 this._handlers = { 37778 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 37779 if (e.namespace && this._core.settings.autoHeight) { 37780 this.update(); 37781 } 37782 }, this), 37783 'changed.owl.carousel': $.proxy(function(e) { 37784 if (e.namespace && this._core.settings.autoHeight && e.property.name === 'position'){ 37785 this.update(); 37786 } 37787 }, this), 37788 'loaded.owl.lazy': $.proxy(function(e) { 37789 if (e.namespace && this._core.settings.autoHeight 37790 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 37791 this.update(); 37792 } 37793 }, this) 37794 }; 37795 37796 // set default options 37797 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 37798 37799 // register event handlers 37800 this._core.$element.on(this._handlers); 37801 this._intervalId = null; 37802 var refThis = this; 37803 37804 // These changes have been taken from a PR by gavrochelegnou proposed in #1575 37805 // and have been made compatible with the latest jQuery version 37806 $(window).on('load', function() { 37807 if (refThis._core.settings.autoHeight) { 37808 refThis.update(); 37809 } 37810 }); 37811 37812 // Autoresize the height of the carousel when window is resized 37813 // When carousel has images, the height is dependent on the width 37814 // and should also change on resize 37815 $(window).resize(function() { 37816 if (refThis._core.settings.autoHeight) { 37817 if (refThis._intervalId != null) { 37818 clearTimeout(refThis._intervalId); 37819 } 37820 37821 refThis._intervalId = setTimeout(function() { 37822 refThis.update(); 37823 }, 250); 37824 } 37825 }); 37826 37827 }; 37828 37829 /** 37830 * Default options. 37831 * @public 37832 */ 37833 AutoHeight.Defaults = { 37834 autoHeight: false, 37835 autoHeightClass: 'owl-height' 37836 }; 37837 37838 /** 37839 * Updates the view. 37840 */ 37841 AutoHeight.prototype.update = function() { 37842 var start = this._core._current, 37843 end = start + this._core.settings.items, 37844 lazyLoadEnabled = this._core.settings.lazyLoad, 37845 visible = this._core.$stage.children().toArray().slice(start, end), 37846 heights = [], 37847 maxheight = 0; 37848 37849 $.each(visible, function(index, item) { 37850 heights.push($(item).height()); 37851 }); 37852 37853 maxheight = Math.max.apply(null, heights); 37854 37855 if (maxheight <= 1 && lazyLoadEnabled && this._previousHeight) { 37856 maxheight = this._previousHeight; 37857 } 37858 37859 this._previousHeight = maxheight; 37860 37861 this._core.$stage.parent() 37862 .height(maxheight) 37863 .addClass(this._core.settings.autoHeightClass); 37864 }; 37865 37866 AutoHeight.prototype.destroy = function() { 37867 var handler, property; 37868 37869 for (handler in this._handlers) { 37870 this._core.$element.off(handler, this._handlers[handler]); 37871 } 37872 for (property in Object.getOwnPropertyNames(this)) { 37873 typeof this[property] !== 'function' && (this[property] = null); 37874 } 37875 }; 37876 37877 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 37878 37879})(window.Zepto || window.jQuery, window, document); 37880 37881/** 37882 * Video Plugin 37883 * @version 2.3.4 37884 * @author Bartosz Wojciechowski 37885 * @author David Deutsch 37886 * @license The MIT License (MIT) 37887 */ 37888;(function($, window, document, undefined) { 37889 37890 /** 37891 * Creates the video plugin. 37892 * @class The Video Plugin 37893 * @param {Owl} carousel - The Owl Carousel 37894 */ 37895 var Video = function(carousel) { 37896 /** 37897 * Reference to the core. 37898 * @protected 37899 * @type {Owl} 37900 */ 37901 this._core = carousel; 37902 37903 /** 37904 * Cache all video URLs. 37905 * @protected 37906 * @type {Object} 37907 */ 37908 this._videos = {}; 37909 37910 /** 37911 * Current playing item. 37912 * @protected 37913 * @type {jQuery} 37914 */ 37915 this._playing = null; 37916 37917 /** 37918 * All event handlers. 37919 * @todo The cloned content removale is too late 37920 * @protected 37921 * @type {Object} 37922 */ 37923 this._handlers = { 37924 'initialized.owl.carousel': $.proxy(function(e) { 37925 if (e.namespace) { 37926 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 37927 } 37928 }, this), 37929 'resize.owl.carousel': $.proxy(function(e) { 37930 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 37931 e.preventDefault(); 37932 } 37933 }, this), 37934 'refreshed.owl.carousel': $.proxy(function(e) { 37935 if (e.namespace && this._core.is('resizing')) { 37936 this._core.$stage.find('.cloned .owl-video-frame').remove(); 37937 } 37938 }, this), 37939 'changed.owl.carousel': $.proxy(function(e) { 37940 if (e.namespace && e.property.name === 'position' && this._playing) { 37941 this.stop(); 37942 } 37943 }, this), 37944 'prepared.owl.carousel': $.proxy(function(e) { 37945 if (!e.namespace) { 37946 return; 37947 } 37948 37949 var $element = $(e.content).find('.owl-video'); 37950 37951 if ($element.length) { 37952 $element.css('display', 'none'); 37953 this.fetch($element, $(e.content)); 37954 } 37955 }, this) 37956 }; 37957 37958 // set default options 37959 this._core.options = $.extend({}, Video.Defaults, this._core.options); 37960 37961 // register event handlers 37962 this._core.$element.on(this._handlers); 37963 37964 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 37965 this.play(e); 37966 }, this)); 37967 }; 37968 37969 /** 37970 * Default options. 37971 * @public 37972 */ 37973 Video.Defaults = { 37974 video: false, 37975 videoHeight: false, 37976 videoWidth: false 37977 }; 37978 37979 /** 37980 * Gets the video ID and the type (YouTube/Vimeo/vzaar only). 37981 * @protected 37982 * @param {jQuery} target - The target containing the video data. 37983 * @param {jQuery} item - The item containing the video. 37984 */ 37985 Video.prototype.fetch = function(target, item) { 37986 var type = (function() { 37987 if (target.attr('data-vimeo-id')) { 37988 return 'vimeo'; 37989 } else if (target.attr('data-vzaar-id')) { 37990 return 'vzaar' 37991 } else { 37992 return 'youtube'; 37993 } 37994 })(), 37995 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'), 37996 width = target.attr('data-width') || this._core.settings.videoWidth, 37997 height = target.attr('data-height') || this._core.settings.videoHeight, 37998 url = target.attr('href'); 37999 38000 if (url) { 38001 38002 /* 38003 Parses the id's out of the following urls (and probably more): 38004 https://www.youtube.com/watch?v=:id 38005 https://youtu.be/:id 38006 https://vimeo.com/:id 38007 https://vimeo.com/channels/:channel/:id 38008 https://vimeo.com/groups/:group/videos/:id 38009 https://app.vzaar.com/videos/:id 38010 38011 Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F 38012 */ 38013 38014 id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com|be\-nocookie\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/); 38015 38016 if (id[3].indexOf('youtu') > -1) { 38017 type = 'youtube'; 38018 } else if (id[3].indexOf('vimeo') > -1) { 38019 type = 'vimeo'; 38020 } else if (id[3].indexOf('vzaar') > -1) { 38021 type = 'vzaar'; 38022 } else { 38023 throw new Error('Video URL not supported.'); 38024 } 38025 id = id[6]; 38026 } else { 38027 throw new Error('Missing video URL.'); 38028 } 38029 38030 this._videos[url] = { 38031 type: type, 38032 id: id, 38033 width: width, 38034 height: height 38035 }; 38036 38037 item.attr('data-video', url); 38038 38039 this.thumbnail(target, this._videos[url]); 38040 }; 38041 38042 /** 38043 * Creates video thumbnail. 38044 * @protected 38045 * @param {jQuery} target - The target containing the video data. 38046 * @param {Object} info - The video info object. 38047 * @see `fetch` 38048 */ 38049 Video.prototype.thumbnail = function(target, video) { 38050 var tnLink, 38051 icon, 38052 path, 38053 dimensions = video.width && video.height ? 'width:' + video.width + 'px;height:' + video.height + 'px;' : '', 38054 customTn = target.find('img'), 38055 srcType = 'src', 38056 lazyClass = '', 38057 settings = this._core.settings, 38058 create = function(path) { 38059 icon = '<div class="owl-video-play-icon"></div>'; 38060 38061 if (settings.lazyLoad) { 38062 tnLink = $('<div/>',{ 38063 "class": 'owl-video-tn ' + lazyClass, 38064 "srcType": path 38065 }); 38066 } else { 38067 tnLink = $( '<div/>', { 38068 "class": "owl-video-tn", 38069 "style": 'opacity:1;background-image:url(' + path + ')' 38070 }); 38071 } 38072 target.after(tnLink); 38073 target.after(icon); 38074 }; 38075 38076 // wrap video content into owl-video-wrapper div 38077 target.wrap( $( '<div/>', { 38078 "class": "owl-video-wrapper", 38079 "style": dimensions 38080 })); 38081 38082 if (this._core.settings.lazyLoad) { 38083 srcType = 'data-src'; 38084 lazyClass = 'owl-lazy'; 38085 } 38086 38087 // custom thumbnail 38088 if (customTn.length) { 38089 create(customTn.attr(srcType)); 38090 customTn.remove(); 38091 return false; 38092 } 38093 38094 if (video.type === 'youtube') { 38095 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 38096 create(path); 38097 } else if (video.type === 'vimeo') { 38098 $.ajax({ 38099 type: 'GET', 38100 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 38101 jsonp: 'callback', 38102 dataType: 'jsonp', 38103 success: function(data) { 38104 path = data[0].thumbnail_large; 38105 create(path); 38106 } 38107 }); 38108 } else if (video.type === 'vzaar') { 38109 $.ajax({ 38110 type: 'GET', 38111 url: '//vzaar.com/api/videos/' + video.id + '.json', 38112 jsonp: 'callback', 38113 dataType: 'jsonp', 38114 success: function(data) { 38115 path = data.framegrab_url; 38116 create(path); 38117 } 38118 }); 38119 } 38120 }; 38121 38122 /** 38123 * Stops the current video. 38124 * @public 38125 */ 38126 Video.prototype.stop = function() { 38127 this._core.trigger('stop', null, 'video'); 38128 this._playing.find('.owl-video-frame').remove(); 38129 this._playing.removeClass('owl-video-playing'); 38130 this._playing = null; 38131 this._core.leave('playing'); 38132 this._core.trigger('stopped', null, 'video'); 38133 }; 38134 38135 /** 38136 * Starts the current video. 38137 * @public 38138 * @param {Event} event - The event arguments. 38139 */ 38140 Video.prototype.play = function(event) { 38141 var target = $(event.target), 38142 item = target.closest('.' + this._core.settings.itemClass), 38143 video = this._videos[item.attr('data-video')], 38144 width = video.width || '100%', 38145 height = video.height || this._core.$stage.height(), 38146 html, 38147 iframe; 38148 38149 if (this._playing) { 38150 return; 38151 } 38152 38153 this._core.enter('playing'); 38154 this._core.trigger('play', null, 'video'); 38155 38156 item = this._core.items(this._core.relative(item.index())); 38157 38158 this._core.reset(item.index()); 38159 38160 html = $( '<iframe frameborder="0" allowfullscreen mozallowfullscreen webkitAllowFullScreen ></iframe>' ); 38161 html.attr( 'height', height ); 38162 html.attr( 'width', width ); 38163 if (video.type === 'youtube') { 38164 html.attr( 'src', '//www.youtube.com/embed/' + video.id + '?autoplay=1&rel=0&v=' + video.id ); 38165 } else if (video.type === 'vimeo') { 38166 html.attr( 'src', '//player.vimeo.com/video/' + video.id + '?autoplay=1' ); 38167 } else if (video.type === 'vzaar') { 38168 html.attr( 'src', '//view.vzaar.com/' + video.id + '/player?autoplay=true' ); 38169 } 38170 38171 iframe = $(html).wrap( '<div class="owl-video-frame" />' ).insertAfter(item.find('.owl-video')); 38172 38173 this._playing = item.addClass('owl-video-playing'); 38174 }; 38175 38176 /** 38177 * Checks whether an video is currently in full screen mode or not. 38178 * @todo Bad style because looks like a readonly method but changes members. 38179 * @protected 38180 * @returns {Boolean} 38181 */ 38182 Video.prototype.isInFullScreen = function() { 38183 var element = document.fullscreenElement || document.mozFullScreenElement || 38184 document.webkitFullscreenElement; 38185 38186 return element && $(element).parent().hasClass('owl-video-frame'); 38187 }; 38188 38189 /** 38190 * Destroys the plugin. 38191 */ 38192 Video.prototype.destroy = function() { 38193 var handler, property; 38194 38195 this._core.$element.off('click.owl.video'); 38196 38197 for (handler in this._handlers) { 38198 this._core.$element.off(handler, this._handlers[handler]); 38199 } 38200 for (property in Object.getOwnPropertyNames(this)) { 38201 typeof this[property] != 'function' && (this[property] = null); 38202 } 38203 }; 38204 38205 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 38206 38207})(window.Zepto || window.jQuery, window, document); 38208 38209/** 38210 * Animate Plugin 38211 * @version 2.3.4 38212 * @author Bartosz Wojciechowski 38213 * @author David Deutsch 38214 * @license The MIT License (MIT) 38215 */ 38216;(function($, window, document, undefined) { 38217 38218 /** 38219 * Creates the animate plugin. 38220 * @class The Navigation Plugin 38221 * @param {Owl} scope - The Owl Carousel 38222 */ 38223 var Animate = function(scope) { 38224 this.core = scope; 38225 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 38226 this.swapping = true; 38227 this.previous = undefined; 38228 this.next = undefined; 38229 38230 this.handlers = { 38231 'change.owl.carousel': $.proxy(function(e) { 38232 if (e.namespace && e.property.name == 'position') { 38233 this.previous = this.core.current(); 38234 this.next = e.property.value; 38235 } 38236 }, this), 38237 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 38238 if (e.namespace) { 38239 this.swapping = e.type == 'translated'; 38240 } 38241 }, this), 38242 'translate.owl.carousel': $.proxy(function(e) { 38243 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 38244 this.swap(); 38245 } 38246 }, this) 38247 }; 38248 38249 this.core.$element.on(this.handlers); 38250 }; 38251 38252 /** 38253 * Default options. 38254 * @public 38255 */ 38256 Animate.Defaults = { 38257 animateOut: false, 38258 animateIn: false 38259 }; 38260 38261 /** 38262 * Toggles the animation classes whenever an translations starts. 38263 * @protected 38264 * @returns {Boolean|undefined} 38265 */ 38266 Animate.prototype.swap = function() { 38267 38268 if (this.core.settings.items !== 1) { 38269 return; 38270 } 38271 38272 if (!$.support.animation || !$.support.transition) { 38273 return; 38274 } 38275 38276 this.core.speed(0); 38277 38278 var left, 38279 clear = $.proxy(this.clear, this), 38280 previous = this.core.$stage.children().eq(this.previous), 38281 next = this.core.$stage.children().eq(this.next), 38282 incoming = this.core.settings.animateIn, 38283 outgoing = this.core.settings.animateOut; 38284 38285 if (this.core.current() === this.previous) { 38286 return; 38287 } 38288 38289 if (outgoing) { 38290 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 38291 previous.one($.support.animation.end, clear) 38292 .css( { 'left': left + 'px' } ) 38293 .addClass('animated owl-animated-out') 38294 .addClass(outgoing); 38295 } 38296 38297 if (incoming) { 38298 next.one($.support.animation.end, clear) 38299 .addClass('animated owl-animated-in') 38300 .addClass(incoming); 38301 } 38302 }; 38303 38304 Animate.prototype.clear = function(e) { 38305 $(e.target).css( { 'left': '' } ) 38306 .removeClass('animated owl-animated-out owl-animated-in') 38307 .removeClass(this.core.settings.animateIn) 38308 .removeClass(this.core.settings.animateOut); 38309 this.core.onTransitionEnd(); 38310 }; 38311 38312 /** 38313 * Destroys the plugin. 38314 * @public 38315 */ 38316 Animate.prototype.destroy = function() { 38317 var handler, property; 38318 38319 for (handler in this.handlers) { 38320 this.core.$element.off(handler, this.handlers[handler]); 38321 } 38322 for (property in Object.getOwnPropertyNames(this)) { 38323 typeof this[property] != 'function' && (this[property] = null); 38324 } 38325 }; 38326 38327 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 38328 38329})(window.Zepto || window.jQuery, window, document); 38330 38331/** 38332 * Autoplay Plugin 38333 * @version 2.3.4 38334 * @author Bartosz Wojciechowski 38335 * @author Artus Kolanowski 38336 * @author David Deutsch 38337 * @author Tom De Caluwé 38338 * @license The MIT License (MIT) 38339 */ 38340;(function($, window, document, undefined) { 38341 38342 /** 38343 * Creates the autoplay plugin. 38344 * @class The Autoplay Plugin 38345 * @param {Owl} scope - The Owl Carousel 38346 */ 38347 var Autoplay = function(carousel) { 38348 /** 38349 * Reference to the core. 38350 * @protected 38351 * @type {Owl} 38352 */ 38353 this._core = carousel; 38354 38355 /** 38356 * The autoplay timeout id. 38357 * @type {Number} 38358 */ 38359 this._call = null; 38360 38361 /** 38362 * Depending on the state of the plugin, this variable contains either 38363 * the start time of the timer or the current timer value if it's 38364 * paused. Since we start in a paused state we initialize the timer 38365 * value. 38366 * @type {Number} 38367 */ 38368 this._time = 0; 38369 38370 /** 38371 * Stores the timeout currently used. 38372 * @type {Number} 38373 */ 38374 this._timeout = 0; 38375 38376 /** 38377 * Indicates whenever the autoplay is paused. 38378 * @type {Boolean} 38379 */ 38380 this._paused = true; 38381 38382 /** 38383 * All event handlers. 38384 * @protected 38385 * @type {Object} 38386 */ 38387 this._handlers = { 38388 'changed.owl.carousel': $.proxy(function(e) { 38389 if (e.namespace && e.property.name === 'settings') { 38390 if (this._core.settings.autoplay) { 38391 this.play(); 38392 } else { 38393 this.stop(); 38394 } 38395 } else if (e.namespace && e.property.name === 'position' && this._paused) { 38396 // Reset the timer. This code is triggered when the position 38397 // of the carousel was changed through user interaction. 38398 this._time = 0; 38399 } 38400 }, this), 38401 'initialized.owl.carousel': $.proxy(function(e) { 38402 if (e.namespace && this._core.settings.autoplay) { 38403 this.play(); 38404 } 38405 }, this), 38406 'play.owl.autoplay': $.proxy(function(e, t, s) { 38407 if (e.namespace) { 38408 this.play(t, s); 38409 } 38410 }, this), 38411 'stop.owl.autoplay': $.proxy(function(e) { 38412 if (e.namespace) { 38413 this.stop(); 38414 } 38415 }, this), 38416 'mouseover.owl.autoplay': $.proxy(function() { 38417 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 38418 this.pause(); 38419 } 38420 }, this), 38421 'mouseleave.owl.autoplay': $.proxy(function() { 38422 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 38423 this.play(); 38424 } 38425 }, this), 38426 'touchstart.owl.core': $.proxy(function() { 38427 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 38428 this.pause(); 38429 } 38430 }, this), 38431 'touchend.owl.core': $.proxy(function() { 38432 if (this._core.settings.autoplayHoverPause) { 38433 this.play(); 38434 } 38435 }, this) 38436 }; 38437 38438 // register event handlers 38439 this._core.$element.on(this._handlers); 38440 38441 // set default options 38442 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 38443 }; 38444 38445 /** 38446 * Default options. 38447 * @public 38448 */ 38449 Autoplay.Defaults = { 38450 autoplay: false, 38451 autoplayTimeout: 5000, 38452 autoplayHoverPause: false, 38453 autoplaySpeed: false 38454 }; 38455 38456 /** 38457 * Transition to the next slide and set a timeout for the next transition. 38458 * @private 38459 * @param {Number} [speed] - The animation speed for the animations. 38460 */ 38461 Autoplay.prototype._next = function(speed) { 38462 this._call = window.setTimeout( 38463 $.proxy(this._next, this, speed), 38464 this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read() 38465 ); 38466 38467 if (this._core.is('interacting') || document.hidden) { 38468 return; 38469 } 38470 this._core.next(speed || this._core.settings.autoplaySpeed); 38471 } 38472 38473 /** 38474 * Reads the current timer value when the timer is playing. 38475 * @public 38476 */ 38477 Autoplay.prototype.read = function() { 38478 return new Date().getTime() - this._time; 38479 }; 38480 38481 /** 38482 * Starts the autoplay. 38483 * @public 38484 * @param {Number} [timeout] - The interval before the next animation starts. 38485 * @param {Number} [speed] - The animation speed for the animations. 38486 */ 38487 Autoplay.prototype.play = function(timeout, speed) { 38488 var elapsed; 38489 38490 if (!this._core.is('rotating')) { 38491 this._core.enter('rotating'); 38492 } 38493 38494 timeout = timeout || this._core.settings.autoplayTimeout; 38495 38496 // Calculate the elapsed time since the last transition. If the carousel 38497 // wasn't playing this calculation will yield zero. 38498 elapsed = Math.min(this._time % (this._timeout || timeout), timeout); 38499 38500 if (this._paused) { 38501 // Start the clock. 38502 this._time = this.read(); 38503 this._paused = false; 38504 } else { 38505 // Clear the active timeout to allow replacement. 38506 window.clearTimeout(this._call); 38507 } 38508 38509 // Adjust the origin of the timer to match the new timeout value. 38510 this._time += this.read() % timeout - elapsed; 38511 38512 this._timeout = timeout; 38513 this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed); 38514 }; 38515 38516 /** 38517 * Stops the autoplay. 38518 * @public 38519 */ 38520 Autoplay.prototype.stop = function() { 38521 if (this._core.is('rotating')) { 38522 // Reset the clock. 38523 this._time = 0; 38524 this._paused = true; 38525 38526 window.clearTimeout(this._call); 38527 this._core.leave('rotating'); 38528 } 38529 }; 38530 38531 /** 38532 * Pauses the autoplay. 38533 * @public 38534 */ 38535 Autoplay.prototype.pause = function() { 38536 if (this._core.is('rotating') && !this._paused) { 38537 // Pause the clock. 38538 this._time = this.read(); 38539 this._paused = true; 38540 38541 window.clearTimeout(this._call); 38542 } 38543 }; 38544 38545 /** 38546 * Destroys the plugin. 38547 */ 38548 Autoplay.prototype.destroy = function() { 38549 var handler, property; 38550 38551 this.stop(); 38552 38553 for (handler in this._handlers) { 38554 this._core.$element.off(handler, this._handlers[handler]); 38555 } 38556 for (property in Object.getOwnPropertyNames(this)) { 38557 typeof this[property] != 'function' && (this[property] = null); 38558 } 38559 }; 38560 38561 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 38562 38563})(window.Zepto || window.jQuery, window, document); 38564 38565/** 38566 * Navigation Plugin 38567 * @version 2.3.4 38568 * @author Artus Kolanowski 38569 * @author David Deutsch 38570 * @license The MIT License (MIT) 38571 */ 38572;(function($, window, document, undefined) { 38573 'use strict'; 38574 38575 /** 38576 * Creates the navigation plugin. 38577 * @class The Navigation Plugin 38578 * @param {Owl} carousel - The Owl Carousel. 38579 */ 38580 var Navigation = function(carousel) { 38581 /** 38582 * Reference to the core. 38583 * @protected 38584 * @type {Owl} 38585 */ 38586 this._core = carousel; 38587 38588 /** 38589 * Indicates whether the plugin is initialized or not. 38590 * @protected 38591 * @type {Boolean} 38592 */ 38593 this._initialized = false; 38594 38595 /** 38596 * The current paging indexes. 38597 * @protected 38598 * @type {Array} 38599 */ 38600 this._pages = []; 38601 38602 /** 38603 * All DOM elements of the user interface. 38604 * @protected 38605 * @type {Object} 38606 */ 38607 this._controls = {}; 38608 38609 /** 38610 * Markup for an indicator. 38611 * @protected 38612 * @type {Array.<String>} 38613 */ 38614 this._templates = []; 38615 38616 /** 38617 * The carousel element. 38618 * @type {jQuery} 38619 */ 38620 this.$element = this._core.$element; 38621 38622 /** 38623 * Overridden methods of the carousel. 38624 * @protected 38625 * @type {Object} 38626 */ 38627 this._overrides = { 38628 next: this._core.next, 38629 prev: this._core.prev, 38630 to: this._core.to 38631 }; 38632 38633 /** 38634 * All event handlers. 38635 * @protected 38636 * @type {Object} 38637 */ 38638 this._handlers = { 38639 'prepared.owl.carousel': $.proxy(function(e) { 38640 if (e.namespace && this._core.settings.dotsData) { 38641 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 38642 $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>'); 38643 } 38644 }, this), 38645 'added.owl.carousel': $.proxy(function(e) { 38646 if (e.namespace && this._core.settings.dotsData) { 38647 this._templates.splice(e.position, 0, this._templates.pop()); 38648 } 38649 }, this), 38650 'remove.owl.carousel': $.proxy(function(e) { 38651 if (e.namespace && this._core.settings.dotsData) { 38652 this._templates.splice(e.position, 1); 38653 } 38654 }, this), 38655 'changed.owl.carousel': $.proxy(function(e) { 38656 if (e.namespace && e.property.name == 'position') { 38657 this.draw(); 38658 } 38659 }, this), 38660 'initialized.owl.carousel': $.proxy(function(e) { 38661 if (e.namespace && !this._initialized) { 38662 this._core.trigger('initialize', null, 'navigation'); 38663 this.initialize(); 38664 this.update(); 38665 this.draw(); 38666 this._initialized = true; 38667 this._core.trigger('initialized', null, 'navigation'); 38668 } 38669 }, this), 38670 'refreshed.owl.carousel': $.proxy(function(e) { 38671 if (e.namespace && this._initialized) { 38672 this._core.trigger('refresh', null, 'navigation'); 38673 this.update(); 38674 this.draw(); 38675 this._core.trigger('refreshed', null, 'navigation'); 38676 } 38677 }, this) 38678 }; 38679 38680 // set default options 38681 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 38682 38683 // register event handlers 38684 this.$element.on(this._handlers); 38685 }; 38686 38687 /** 38688 * Default options. 38689 * @public 38690 * @todo Rename `slideBy` to `navBy` 38691 */ 38692 Navigation.Defaults = { 38693 nav: false, 38694 navText: [ 38695 '<span aria-label="' + 'Previous' + '">‹</span>', 38696 '<span aria-label="' + 'Next' + '">›</span>' 38697 ], 38698 navSpeed: false, 38699 navElement: 'button type="button" role="presentation"', 38700 navContainer: false, 38701 navContainerClass: 'owl-nav', 38702 navClass: [ 38703 'owl-prev', 38704 'owl-next' 38705 ], 38706 slideBy: 1, 38707 dotClass: 'owl-dot', 38708 dotsClass: 'owl-dots', 38709 dots: true, 38710 dotsEach: false, 38711 dotsData: false, 38712 dotsSpeed: false, 38713 dotsContainer: false 38714 }; 38715 38716 /** 38717 * Initializes the layout of the plugin and extends the carousel. 38718 * @protected 38719 */ 38720 Navigation.prototype.initialize = function() { 38721 var override, 38722 settings = this._core.settings; 38723 38724 // create DOM structure for relative navigation 38725 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 38726 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 38727 38728 this._controls.$previous = $('<' + settings.navElement + '>') 38729 .addClass(settings.navClass[0]) 38730 .html(settings.navText[0]) 38731 .prependTo(this._controls.$relative) 38732 .on('click', $.proxy(function(e) { 38733 this.prev(settings.navSpeed); 38734 }, this)); 38735 this._controls.$next = $('<' + settings.navElement + '>') 38736 .addClass(settings.navClass[1]) 38737 .html(settings.navText[1]) 38738 .appendTo(this._controls.$relative) 38739 .on('click', $.proxy(function(e) { 38740 this.next(settings.navSpeed); 38741 }, this)); 38742 38743 // create DOM structure for absolute navigation 38744 if (!settings.dotsData) { 38745 this._templates = [ $('<button role="button">') 38746 .addClass(settings.dotClass) 38747 .append($('<span>')) 38748 .prop('outerHTML') ]; 38749 } 38750 38751 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 38752 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 38753 38754 this._controls.$absolute.on('click', 'button', $.proxy(function(e) { 38755 var index = $(e.target).parent().is(this._controls.$absolute) 38756 ? $(e.target).index() : $(e.target).parent().index(); 38757 38758 e.preventDefault(); 38759 38760 this.to(index, settings.dotsSpeed); 38761 }, this)); 38762 38763 /*$el.on('focusin', function() { 38764 $(document).off(".carousel"); 38765 38766 $(document).on('keydown.carousel', function(e) { 38767 if(e.keyCode == 37) { 38768 $el.trigger('prev.owl') 38769 } 38770 if(e.keyCode == 39) { 38771 $el.trigger('next.owl') 38772 } 38773 }); 38774 });*/ 38775 38776 // override public methods of the carousel 38777 for (override in this._overrides) { 38778 this._core[override] = $.proxy(this[override], this); 38779 } 38780 }; 38781 38782 /** 38783 * Destroys the plugin. 38784 * @protected 38785 */ 38786 Navigation.prototype.destroy = function() { 38787 var handler, control, property, override, settings; 38788 settings = this._core.settings; 38789 38790 for (handler in this._handlers) { 38791 this.$element.off(handler, this._handlers[handler]); 38792 } 38793 for (control in this._controls) { 38794 if (control === '$relative' && settings.navContainer) { 38795 this._controls[control].html(''); 38796 } else { 38797 this._controls[control].remove(); 38798 } 38799 } 38800 for (override in this.overides) { 38801 this._core[override] = this._overrides[override]; 38802 } 38803 for (property in Object.getOwnPropertyNames(this)) { 38804 typeof this[property] != 'function' && (this[property] = null); 38805 } 38806 }; 38807 38808 /** 38809 * Updates the internal state. 38810 * @protected 38811 */ 38812 Navigation.prototype.update = function() { 38813 var i, j, k, 38814 lower = this._core.clones().length / 2, 38815 upper = lower + this._core.items().length, 38816 maximum = this._core.maximum(true), 38817 settings = this._core.settings, 38818 size = settings.center || settings.autoWidth || settings.dotsData 38819 ? 1 : settings.dotsEach || settings.items; 38820 38821 if (settings.slideBy !== 'page') { 38822 settings.slideBy = Math.min(settings.slideBy, settings.items); 38823 } 38824 38825 if (settings.dots || settings.slideBy == 'page') { 38826 this._pages = []; 38827 38828 for (i = lower, j = 0, k = 0; i < upper; i++) { 38829 if (j >= size || j === 0) { 38830 this._pages.push({ 38831 start: Math.min(maximum, i - lower), 38832 end: i - lower + size - 1 38833 }); 38834 if (Math.min(maximum, i - lower) === maximum) { 38835 break; 38836 } 38837 j = 0, ++k; 38838 } 38839 j += this._core.mergers(this._core.relative(i)); 38840 } 38841 } 38842 }; 38843 38844 /** 38845 * Draws the user interface. 38846 * @todo The option `dotsData` wont work. 38847 * @protected 38848 */ 38849 Navigation.prototype.draw = function() { 38850 var difference, 38851 settings = this._core.settings, 38852 disabled = this._core.items().length <= settings.items, 38853 index = this._core.relative(this._core.current()), 38854 loop = settings.loop || settings.rewind; 38855 38856 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 38857 38858 if (settings.nav) { 38859 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 38860 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 38861 } 38862 38863 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 38864 38865 if (settings.dots) { 38866 difference = this._pages.length - this._controls.$absolute.children().length; 38867 38868 if (settings.dotsData && difference !== 0) { 38869 this._controls.$absolute.html(this._templates.join('')); 38870 } else if (difference > 0) { 38871 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 38872 } else if (difference < 0) { 38873 this._controls.$absolute.children().slice(difference).remove(); 38874 } 38875 38876 this._controls.$absolute.find('.active').removeClass('active'); 38877 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 38878 } 38879 }; 38880 38881 /** 38882 * Extends event data. 38883 * @protected 38884 * @param {Event} event - The event object which gets thrown. 38885 */ 38886 Navigation.prototype.onTrigger = function(event) { 38887 var settings = this._core.settings; 38888 38889 event.page = { 38890 index: $.inArray(this.current(), this._pages), 38891 count: this._pages.length, 38892 size: settings && (settings.center || settings.autoWidth || settings.dotsData 38893 ? 1 : settings.dotsEach || settings.items) 38894 }; 38895 }; 38896 38897 /** 38898 * Gets the current page position of the carousel. 38899 * @protected 38900 * @returns {Number} 38901 */ 38902 Navigation.prototype.current = function() { 38903 var current = this._core.relative(this._core.current()); 38904 return $.grep(this._pages, $.proxy(function(page, index) { 38905 return page.start <= current && page.end >= current; 38906 }, this)).pop(); 38907 }; 38908 38909 /** 38910 * Gets the current succesor/predecessor position. 38911 * @protected 38912 * @returns {Number} 38913 */ 38914 Navigation.prototype.getPosition = function(successor) { 38915 var position, length, 38916 settings = this._core.settings; 38917 38918 if (settings.slideBy == 'page') { 38919 position = $.inArray(this.current(), this._pages); 38920 length = this._pages.length; 38921 successor ? ++position : --position; 38922 position = this._pages[((position % length) + length) % length].start; 38923 } else { 38924 position = this._core.relative(this._core.current()); 38925 length = this._core.items().length; 38926 successor ? position += settings.slideBy : position -= settings.slideBy; 38927 } 38928 38929 return position; 38930 }; 38931 38932 /** 38933 * Slides to the next item or page. 38934 * @public 38935 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38936 */ 38937 Navigation.prototype.next = function(speed) { 38938 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 38939 }; 38940 38941 /** 38942 * Slides to the previous item or page. 38943 * @public 38944 * @param {Number} [speed=false] - The time in milliseconds for the transition. 38945 */ 38946 Navigation.prototype.prev = function(speed) { 38947 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 38948 }; 38949 38950 /** 38951 * Slides to the specified item or page. 38952 * @public 38953 * @param {Number} position - The position of the item or page. 38954 * @param {Number} [speed] - The time in milliseconds for the transition. 38955 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 38956 */ 38957 Navigation.prototype.to = function(position, speed, standard) { 38958 var length; 38959 38960 if (!standard && this._pages.length) { 38961 length = this._pages.length; 38962 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 38963 } else { 38964 $.proxy(this._overrides.to, this._core)(position, speed); 38965 } 38966 }; 38967 38968 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 38969 38970})(window.Zepto || window.jQuery, window, document); 38971 38972/** 38973 * Hash Plugin 38974 * @version 2.3.4 38975 * @author Artus Kolanowski 38976 * @author David Deutsch 38977 * @license The MIT License (MIT) 38978 */ 38979;(function($, window, document, undefined) { 38980 'use strict'; 38981 38982 /** 38983 * Creates the hash plugin. 38984 * @class The Hash Plugin 38985 * @param {Owl} carousel - The Owl Carousel 38986 */ 38987 var Hash = function(carousel) { 38988 /** 38989 * Reference to the core. 38990 * @protected 38991 * @type {Owl} 38992 */ 38993 this._core = carousel; 38994 38995 /** 38996 * Hash index for the items. 38997 * @protected 38998 * @type {Object} 38999 */ 39000 this._hashes = {}; 39001 39002 /** 39003 * The carousel element. 39004 * @type {jQuery} 39005 */ 39006 this.$element = this._core.$element; 39007 39008 /** 39009 * All event handlers. 39010 * @protected 39011 * @type {Object} 39012 */ 39013 this._handlers = { 39014 'initialized.owl.carousel': $.proxy(function(e) { 39015 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 39016 $(window).trigger('hashchange.owl.navigation'); 39017 } 39018 }, this), 39019 'prepared.owl.carousel': $.proxy(function(e) { 39020 if (e.namespace) { 39021 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 39022 39023 if (!hash) { 39024 return; 39025 } 39026 39027 this._hashes[hash] = e.content; 39028 } 39029 }, this), 39030 'changed.owl.carousel': $.proxy(function(e) { 39031 if (e.namespace && e.property.name === 'position') { 39032 var current = this._core.items(this._core.relative(this._core.current())), 39033 hash = $.map(this._hashes, function(item, hash) { 39034 return item === current ? hash : null; 39035 }).join(); 39036 39037 if (!hash || window.location.hash.slice(1) === hash) { 39038 return; 39039 } 39040 39041 window.location.hash = hash; 39042 } 39043 }, this) 39044 }; 39045 39046 // set default options 39047 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 39048 39049 // register the event handlers 39050 this.$element.on(this._handlers); 39051 39052 // register event listener for hash navigation 39053 $(window).on('hashchange.owl.navigation', $.proxy(function(e) { 39054 var hash = window.location.hash.substring(1), 39055 items = this._core.$stage.children(), 39056 position = this._hashes[hash] && items.index(this._hashes[hash]); 39057 39058 if (position === undefined || position === this._core.current()) { 39059 return; 39060 } 39061 39062 this._core.to(this._core.relative(position), false, true); 39063 }, this)); 39064 }; 39065 39066 /** 39067 * Default options. 39068 * @public 39069 */ 39070 Hash.Defaults = { 39071 URLhashListener: false 39072 }; 39073 39074 /** 39075 * Destroys the plugin. 39076 * @public 39077 */ 39078 Hash.prototype.destroy = function() { 39079 var handler, property; 39080 39081 $(window).off('hashchange.owl.navigation'); 39082 39083 for (handler in this._handlers) { 39084 this._core.$element.off(handler, this._handlers[handler]); 39085 } 39086 for (property in Object.getOwnPropertyNames(this)) { 39087 typeof this[property] != 'function' && (this[property] = null); 39088 } 39089 }; 39090 39091 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 39092 39093})(window.Zepto || window.jQuery, window, document); 39094 39095/** 39096 * Support Plugin 39097 * 39098 * @version 2.3.4 39099 * @author Vivid Planet Software GmbH 39100 * @author Artus Kolanowski 39101 * @author David Deutsch 39102 * @license The MIT License (MIT) 39103 */ 39104;(function($, window, document, undefined) { 39105 39106 var style = $('<support>').get(0).style, 39107 prefixes = 'Webkit Moz O ms'.split(' '), 39108 events = { 39109 transition: { 39110 end: { 39111 WebkitTransition: 'webkitTransitionEnd', 39112 MozTransition: 'transitionend', 39113 OTransition: 'oTransitionEnd', 39114 transition: 'transitionend' 39115 } 39116 }, 39117 animation: { 39118 end: { 39119 WebkitAnimation: 'webkitAnimationEnd', 39120 MozAnimation: 'animationend', 39121 OAnimation: 'oAnimationEnd', 39122 animation: 'animationend' 39123 } 39124 } 39125 }, 39126 tests = { 39127 csstransforms: function() { 39128 return !!test('transform'); 39129 }, 39130 csstransforms3d: function() { 39131 return !!test('perspective'); 39132 }, 39133 csstransitions: function() { 39134 return !!test('transition'); 39135 }, 39136 cssanimations: function() { 39137 return !!test('animation'); 39138 } 39139 }; 39140 39141 function test(property, prefixed) { 39142 var result = false, 39143 upper = property.charAt(0).toUpperCase() + property.slice(1); 39144 39145 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 39146 if (style[property] !== undefined) { 39147 result = prefixed ? property : true; 39148 return false; 39149 } 39150 }); 39151 39152 return result; 39153 } 39154 39155 function prefixed(property) { 39156 return test(property, true); 39157 } 39158 39159 if (tests.csstransitions()) { 39160 /* jshint -W053 */ 39161 $.support.transition = new String(prefixed('transition')) 39162 $.support.transition.end = events.transition.end[ $.support.transition ]; 39163 } 39164 39165 if (tests.cssanimations()) { 39166 /* jshint -W053 */ 39167 $.support.animation = new String(prefixed('animation')) 39168 $.support.animation.end = events.animation.end[ $.support.animation ]; 39169 } 39170 39171 if (tests.csstransforms()) { 39172 /* jshint -W053 */ 39173 $.support.transform = new String(prefixed('transform')); 39174 $.support.transform3d = tests.csstransforms3d(); 39175 } 39176 39177})(window.Zepto || window.jQuery, window, document);
39178 39179/*! 39180 autosize 4.0.2 39181 license: MIT 39182 http://www.jacklmoore.com/autosize 39183*/ 39184(function (global, factory) { 39185 if (typeof define === "function" && define.amd) { 39186 define(['module', 'exports'], factory); 39187 } else if (typeof exports !== "undefined") { 39188 factory(module, exports); 39189 } else { 39190 var mod = { 39191 exports: {} 39192 }; 39193 factory(mod, mod.exports); 39194 global.autosize = mod.exports; 39195 } 39196})(this, function (module, exports) { 39197 'use strict'; 39198 39199 var map = typeof Map === "function" ? new Map() : function () { 39200 var keys = []; 39201 var values = []; 39202 39203 return { 39204 has: function has(key) { 39205 return keys.indexOf(key) > -1; 39206 }, 39207 get: function get(key) { 39208 return values[keys.indexOf(key)]; 39209 }, 39210 set: function set(key, value) { 39211 if (keys.indexOf(key) === -1) { 39212 keys.push(key); 39213 values.push(value); 39214 } 39215 }, 39216 delete: function _delete(key) { 39217 var index = keys.indexOf(key); 39218 if (index > -1) { 39219 keys.splice(index, 1); 39220 values.splice(index, 1); 39221 } 39222 } 39223 }; 39224 }(); 39225 39226 var createEvent = function createEvent(name) { 39227 return new Event(name, { bubbles: true }); 39228 }; 39229 try { 39230 new Event('test'); 39231 } catch (e) { 39232 // IE does not support `new Event()` 39233 createEvent = function createEvent(name) { 39234 var evt = document.createEvent('Event'); 39235 evt.initEvent(name, true, false); 39236 return evt; 39237 }; 39238 } 39239 39240 function assign(ta) { 39241 if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return; 39242 39243 var heightOffset = null; 39244 var clientWidth = null; 39245 var cachedHeight = null; 39246 39247 function init() { 39248 var style = window.getComputedStyle(ta, null); 39249 39250 if (style.resize === 'vertical') { 39251 ta.style.resize = 'none'; 39252 } else if (style.resize === 'both') { 39253 ta.style.resize = 'horizontal'; 39254 } 39255 39256 if (style.boxSizing === 'content-box') { 39257 heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)); 39258 } else { 39259 heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); 39260 } 39261 // Fix when a textarea is not on document body and heightOffset is Not a Number 39262 if (isNaN(heightOffset)) { 39263 heightOffset = 0; 39264 } 39265 39266 update(); 39267 } 39268 39269 function changeOverflow(value) { 39270 { 39271 // Chrome/Safari-specific fix: 39272 // When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space 39273 // made available by removing the scrollbar. The following forces the necessary text reflow. 39274 var width = ta.style.width; 39275 ta.style.width = '0px'; 39276 // Force reflow: 39277 /* jshint ignore:start */ 39278 ta.offsetWidth; 39279 /* jshint ignore:end */ 39280 ta.style.width = width; 39281 } 39282 39283 ta.style.overflowY = value; 39284 } 39285 39286 function getParentOverflows(el) { 39287 var arr = []; 39288 39289 while (el && el.parentNode && el.parentNode instanceof Element) { 39290 if (el.parentNode.scrollTop) { 39291 arr.push({ 39292 node: el.parentNode, 39293 scrollTop: el.parentNode.scrollTop 39294 }); 39295 } 39296 el = el.parentNode; 39297 } 39298 39299 return arr; 39300 } 39301 39302 function resize() { 39303 if (ta.scrollHeight === 0) { 39304 // If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM. 39305 return; 39306 } 39307 39308 var overflows = getParentOverflows(ta); 39309 var docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240) 39310 39311 ta.style.height = ''; 39312 ta.style.height = ta.scrollHeight + heightOffset + 'px'; 39313 39314 // used to check if an update is actually necessary on window.resize 39315 clientWidth = ta.clientWidth; 39316 39317 // prevents scroll-position jumping 39318 overflows.forEach(function (el) { 39319 el.node.scrollTop = el.scrollTop; 39320 }); 39321 39322 if (docTop) { 39323 document.documentElement.scrollTop = docTop; 39324 } 39325 } 39326 39327 function update() { 39328 resize(); 39329 39330 var styleHeight = Math.round(parseFloat(ta.style.height)); 39331 var computed = window.getComputedStyle(ta, null); 39332 39333 // Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box 39334 var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight; 39335 39336 // The actual height not matching the style height (set via the resize method) indicates that 39337 // the max-height has been exceeded, in which case the overflow should be allowed. 39338 if (actualHeight < styleHeight) { 39339 if (computed.overflowY === 'hidden') { 39340 changeOverflow('scroll'); 39341 resize(); 39342 actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight; 39343 } 39344 } else { 39345 // Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands. 39346 if (computed.overflowY !== 'hidden') { 39347 changeOverflow('hidden'); 39348 resize(); 39349 actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight; 39350 } 39351 } 39352 39353 if (cachedHeight !== actualHeight) { 39354 cachedHeight = actualHeight; 39355 var evt = createEvent('autosize:resized');
39356 try { 39357 ta.dispatchEvent(evt); 39358 } catch (err) { 39359 // Firefox will throw an error on dispatchEvent for a detached element 39360 // https://bugzilla.mozilla.org/show_bug.cgi?id=889376 39361 } 39362 } 39363 } 39364 39365 var pageResize = function pageResize() { 39366 if (ta.clientWidth !== clientWidth) { 39367 update(); 39368 } 39369 }; 39370 39371 var destroy = function (style) { 39372 window.removeEventListener('resize', pageResize, false); 39373 ta.removeEventListener('input', update, false); 39374 ta.removeEventListener('keyup', update, false); 39375 ta.removeEventListener('autosize:destroy', destroy, false); 39376 ta.removeEventListener('autosize:update', update, false); 39377 39378 Object.keys(style).forEach(function (key) { 39379 ta.style[key] = style[key]; 39380 }); 39381 39382 map.delete(ta); 39383 }.bind(ta, { 39384 height: ta.style.height, 39385 resize: ta.style.resize, 39386 overflowY: ta.style.overflowY, 39387 overflowX: ta.style.overflowX, 39388 wordWrap: ta.style.wordWrap 39389 }); 39390 39391 ta.addEventListener('autosize:destroy', destroy, false); 39392 39393 // IE9 does not fire onpropertychange or oninput for deletions, 39394 // so binding to onkeyup to catch most of those events. 39395 // There is no way that I know of to detect something like 'cut' in IE9. 39396 if ('onpropertychange' in ta && 'oninput' in ta) { 39397 ta.addEventListener('keyup', update, false); 39398 } 39399 39400 window.addEventListener('resize', pageResize, false); 39401 ta.addEventListener('input', update, false); 39402 ta.addEventListener('autosize:update', update, false); 39403 ta.style.overflowX = 'hidden'; 39404 ta.style.wordWrap = 'break-word'; 39405 39406 map.set(ta, { 39407 destroy: destroy, 39408 update: update 39409 }); 39410 39411 init(); 39412 } 39413 39414 function destroy(ta) { 39415 var methods = map.get(ta); 39416 if (methods) { 39417 methods.destroy(); 39418 } 39419 } 39420 39421 function update(ta) { 39422 var methods = map.get(ta); 39423 if (methods) { 39424 methods.update(); 39425 } 39426 } 39427 39428 var autosize = null; 39429 39430 // Do nothing in Node.js environment and IE8 (or lower) 39431 if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') { 39432 autosize = function autosize(el) { 39433 return el; 39434 }; 39435 autosize.destroy = function (el) { 39436 return el; 39437 }; 39438 autosize.update = function (el) { 39439 return el; 39440 }; 39441 } else { 39442 autosize = function autosize(el, options) { 39443 if (el) { 39444 Array.prototype.forEach.call(el.length ? el : [el], function (x) { 39445 return assign(x, options); 39446 }); 39447 } 39448 return el; 39449 }; 39450 autosize.destroy = function (el) { 39451 if (el) { 39452 Array.prototype.forEach.call(el.length ? el : [el], destroy); 39453 } 39454 return el; 39455 }; 39456 autosize.update = function (el) { 39457 if (el) { 39458 Array.prototype.forEach.call(el.length ? el : [el], update); 39459 } 39460 return el; 39461 }; 39462 } 39463 39464 exports.default = autosize; 39465 module.exports = exports['default']; 39466}); 39467/*! 39468 * clipboard.js v2.0.4 39469 * https://zenorocha.github.io/clipboard.js 39470 * 39471 * Licensed MIT © Zeno Rocha 39472 */ 39473!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exp
39473orts.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=o(n(1)),c=o(n(3)),u=o(n(4));function o(t){return t&&t.__esModule?t:{default:t}}var l=function(t){function o(t,e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));return n.resolveOptions(e),n.listenClick(t),n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,c.default),i(o,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===r(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=(0,u.default)(t,"click",function(t){return e.onClick(t)})}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new a.default({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return s("action",t)}},{key:"defaultTarget",value:function(t){var e=s("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return s("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach(function(t){n=n&&!!document.queryCommandSupported(t)}),n}}]),o}();function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}t.exports=l},function(t,e,n){"use strict";var o,r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),t}}(),a=n(2),c=(o=a)&&o.__esModule?o:{default:o};var u=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.resolveOptions(t),this.initSelection()}return i(e,[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}}
vendor: 2,910 bytes, line 39473
39473,{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,c.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=(0,c.default)(this.target),this.copyText()}},{key:"copyText",value:function(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),e}();t.exports=u},function(t,e){t.exports=function(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}
39473else{t.hasAttribute("contenteditable")&&t.focus();var o=window.getSelection(),r=document.createRange();r.selectNodeContents(t),o.removeAllRanges(),o.addRange(r),e=o.toString()}return e}},function(t,e){function n(){}n.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var o=this;function r(){o.off(t,r),e.apply(n,arguments)}return r._=e,this.on(t,r,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,r=n.length;o<r;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],r=[];if(o&&e)for(var i=0,a=o.length;i<a;i++)o[i].fn!==e&&o[i].fn._!==e&&r.push(o[i]);return r.length?n[t]=r:delete n[t],this}},t.exports=n},function(t,e,n){var d=n(5),h=n(6);t.exports=function(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!d.string(e))throw new TypeError("Second argument must be a String");if(!d.fn(n))throw new TypeError("Third argument must be a Function");if(d.node(t))return s=e,f=n,(l=t).addEventListener(s,f),{destroy:function(){l.removeEventListener(s,f)}};if(d.nodeList(t))return a=t,c=e,u=n,Array.prototype.forEach.call(a,function(t){t.addEventListener(c,u)}),{destroy:function(){Array.prototype.forEach.call(a,function(t){t.removeEventListener(c,u)})}};if(d.string(t))return o=t,r=e,i=n,h(document.body,o,r,i);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList");var o,r,i,a,c,u,l,s,f}},function(t,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},function(t,e,n){var a=n(7);function i(t,e,n,o,r){var i=function(e,n,t,o){return function(t){t.delegateTarget=a(t.target,n),t.delegateTarget&&o.call(e,t)}}.apply(this,arguments);return t.addEventListener(n,i,r),{destroy:function(){t.removeEventListener(n,i,r)}}}t.exports=function(t,e,n,o,r){return"function"==typeof t.addEventListener?i.apply(null,arguments):"function"==typeof n?i.bind(null,document).apply(null,arguments):("string"==typeof t&&(t=document.querySelectorAll(t)),Array.prototype.map.call(t,function(t){return i(t,e,n,o,r)}))}},function(t,e){if("undefined"!=typeof Element&&!Element.prototype.matches){var n=Element.prototype;n.matches=n.matchesSelector||n.mozMatchesSelector||n.msMatchesSelector||n.oMatchesSelector||n.webkitMatchesSelector}t.exports=function(t,e){for(;t&&9!==t.nodeType;){if("function"==typeof t.matches&&t.matches(e))return t;t=t.parentNode}}}])}); 39474"use strict"; 39475 39476var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 39477 39478function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 39479 39480function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 39481 39482function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 39483 39484/* 39485 * 39486 * More info at [www.dropzonejs.com](http://www.dropzonejs.com) 39487 * 39488 * Copyright (c) 2012, Matias Meno 39489 * 39490 * Permission is hereby granted, free of charge, to any person obtaining a copy 39491 * of this software and associated documentation files (the "Software"), to deal 39492 * in the Software without restriction, including without limitation the rights 39493 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39494 * copies of the Software, and to permit persons to whom the Software is 39495 * furnished to do so, subject to the following conditions: 39496 * 39497 * The above copyright notice and this permission notice shall be included in 39498 * all copies or substantial portions of the Software. 39499 * 39500 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39501 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39502 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 39503 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 39504 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 39505 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 39506 * THE SOFTWARE. 39507 * 39508 */ 39509 39510// The Emitter class provides the ability to call `.on()` on Dropzone to listen 39511// to events. 39512// It is strongly based on component's emitter class, and I removed the 39513// functionality because of the dependency hell with different frameworks. 39514var Emitter = function () { 39515 function Emitter() { 39516 _classCallCheck(this, Emitter); 39517 } 39518 39519 _createClass(Emitter, [{ 39520 key: "on", 39521 39522 // Add an event listener for given event 39523 value: function on(event, fn) { 39524 this._callbacks = this._callbacks || {}; 39525 // Create namespace for this event 39526 if (!this._callbacks[event]) { 39527 this._callbacks[event] = []; 39528 } 39529 this._callbacks[event].push(fn); 39530 return this; 39531 } 39532 }, { 39533 key: "emit", 39534 value: function emit(event) { 39535 this._callbacks = this._callbacks || {}; 39536 var callbacks = this._callbacks[event]; 39537 39538 if (callbacks) { 39539 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 39540 args[_key - 1] = arguments[_key]; 39541 } 39542 39543 for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 39544 var _ref; 39545 39546 if (_isArray) { 39547 if (_i >= _iterator.length) break; 39548 _ref = _iterator[_i++]; 39549 } else { 39550 _i = _iterator.next(); 39551 if (_i.done) break; 39552 _ref = _i.value; 39553 } 39554 39555 var callback = _ref; 39556 39557 callback.apply(this, args); 39558 } 39559 } 39560 39561 return this; 39562 } 39563 39564 // Remove event listener for given event. If fn is not provided, all event 39565 // listeners for that event will be removed. If neither is provided, all 39566 // event listeners will be removed. 39567 39568 }, { 39569 key: "off", 39570 value: function off(event, fn) { 39571 if (!this._callbacks || arguments.length === 0) { 39572 this._callbacks = {}; 39573 return this; 39574 } 39575 39576 // specific event 39577 var callbacks = this._callbacks[event]; 39578 if (!callbacks) { 39579 return this; 39580 } 39581 39582 // remove all handlers 39583 if (arguments.length === 1) { 39584 delete this._callbacks[event]; 39585 return this; 39586 } 39587 39588 // remove specific handler 39589 for (var i = 0; i < callbacks.length; i++) { 39590 var callback = callbacks[i]; 39591 if (callback === fn) { 39592 callbacks.splice(i, 1); 39593 break; 39594 } 39595 } 39596 39597 return this; 39598 } 39599 }]); 39600 39601 return Emitter; 39602}(); 39603 39604var Dropzone = function (_Emitter) { 39605 _inherits(Dropzone, _Emitter); 39606 39607 _createClass(Dropzone, null, [{ 39608 key: "initClass", 39609 value: function initClass() { 39610 39611 // Exposing the emitter class, mainly for tests 39612 this.prototype.Emitter = Emitter; 39613 39614 /* 39615 This is a list of all available events you can register on a dropzone object. 39616 You can register an event handler like this: 39617 dropzone.on("dragEnter", function() { }); 39618 */ 39619 this.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"]; 39620 39621 this.prototype.defaultOptions = { 39622 /** 39623 * Has to be specified on elements other than form (or when the form 39624 * doesn't have an `action` attribute). You can also 39625 * provide a function that will be called with `files` and 39626 * must return the url (since `v3.12.0`) 39627 */ 39628 url: null, 39629 39630 /** 39631 * Can be changed to `"put"` if necessary. You can also provide a function 39632 * that will be called with `files` and must return the method (since `v3.12.0`).
39633 */ 39634 method: "post", 39635 39636 /** 39637 * Will be set on the XHRequest. 39638 */ 39639 withCredentials: false, 39640 39641 /** 39642 * The timeout for the XHR requests in milliseconds (since `v4.4.0`). 39643 */ 39644 timeout: 30000, 39645 39646 /** 39647 * How many file uploads to process in parallel (See the 39648 * Enqueuing file uploads* documentation section for more info) 39649 */ 39650 parallelUploads: 2, 39651 39652 /** 39653 * Whether to send multiple files in one request. If 39654 * this it set to true, then the fallback file input element will 39655 * have the `multiple` attribute as well. This option will 39656 * also trigger additional events (like `processingmultiple`). See the events 39657 * documentation section for more information. 39658 */ 39659 uploadMultiple: false, 39660 39661 /** 39662 * Whether you want files to be uploaded in chunks to your server. This can't be 39663 * used in combination with `uploadMultiple`. 39664 * 39665 * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload. 39666 */ 39667 chunking: false, 39668 39669 /** 39670 * If `chunking` is enabled, this defines whether **every** file should be chunked, 39671 * even if the file size is below chunkSize. This means, that the additional chunk 39672 * form data will be submitted and the `chunksUploaded` callback will be invoked. 39673 */ 39674 forceChunking: false, 39675 39676 /** 39677 * If `chunking` is `true`, then this defines the chunk size in bytes. 39678 */ 39679 chunkSize: 2000000, 39680 39681 /** 39682 * If `true`, the individual chunks of a file are being uploaded simultaneously. 39683 */ 39684 parallelChunkUploads: false, 39685 39686 /** 39687 * Whether a chunk should be retried if it fails. 39688 */ 39689 retryChunks: false, 39690 39691 /** 39692 * If `retryChunks` is true, how many times should it be retried. 39693 */ 39694 retryChunksLimit: 3, 39695 39696 /** 39697 * If not `null` defines how many files this Dropzone handles. If it exceeds, 39698 * the event `maxfilesexceeded` will be called. The dropzone element gets the 39699 * class `dz-max-files-reached` accordingly so you can provide visual feedback. 39700 */ 39701 maxFilesize: 256, 39702 39703 /** 39704 * The name of the file param that gets transferred. 39705 * **NOTE**: If you have the option `uploadMultiple` set to `true`, then 39706 * Dropzone will append `[]` to the name. 39707 */ 39708 paramName: "file", 39709 39710 /** 39711 * Whether thumbnails for images should be generated 39712 */ 39713 createImageThumbnails: true, 39714 39715 /** 39716 * In MB. When the filename exceeds this limit, the thumbnail will not be generated. 39717 */ 39718 maxThumbnailFilesize: 10, 39719 39720 /** 39721 * If `null`, the ratio of the image will be used to calculate it. 39722 */ 39723 thumbnailWidth: 120, 39724 39725 /** 39726 * The same as `thumbnailWidth`. If both are null, images will not be resized. 39727 */ 39728 thumbnailHeight: 120, 39729 39730 /** 39731 * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided. 39732 * Can be either `contain` or `crop`. 39733 */ 39734 thumbnailMethod: 'crop', 39735 39736 /** 39737 * If set, images will be resized to these dimensions before being **uploaded**. 39738 * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect 39739 * ratio of the file will be preserved. 39740 * 39741 * The `options.transformFile` function uses these options, so if the `transformFile` function 39742 * is overridden, these options don't do anything. 39743 */ 39744 resizeWidth: null, 39745 39746 /** 39747 * See `resizeWidth`. 39748 */ 39749 resizeHeight: null, 39750 39751 /** 39752 * The mime type of the resized image (before it gets uploaded to the server). 39753 * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`. 39754 * See `resizeWidth` for more information. 39755 */ 39756 resizeMimeType: null, 39757 39758 /** 39759 * The quality of the resized images. See `resizeWidth`. 39760 */ 39761 resizeQuality: 0.8, 39762 39763 /** 39764 * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided. 39765 * Can be either `contain` or `crop`. 39766 */ 39767 resizeMethod: 'contain', 39768 39769 /** 39770 * The base that is used to calculate the filesize. You can change this to 39771 * 1024 if you would rather display kibibytes, mebibytes, etc... 39772 * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`. 39773 * You can change this to `1024` if you don't care about validity. 39774 */ 39775 filesizeBase: 1000, 39776 39777 /** 39778 * Can be used to limit the maximum number of files that will be handled by this Dropzone 39779 */ 39780 maxFiles: null, 39781 39782 /** 39783 * An optional object to send additional headers to the server. Eg: 39784 * `{ "My-Awesome-Header": "header value" }` 39785 */ 39786 headers: null, 39787 39788 /** 39789 * If `true`, the dropzone element itself will be clickable, if `false` 39790 * nothing will be clickable. 39791 * 39792 * You can also pass an HTML element, a CSS selector (for multiple elements) 39793 * or an array of those. In that case, all of those elements will trigger an 39794 * upload when clicked. 39795 */ 39796 clickable: true, 39797 39798 /** 39799 * Whether hidden files in directories should be ignored. 39800 */ 39801 ignoreHiddenFiles: true, 39802 39803 /** 39804 * The default implementation of `accept` checks the file's mime type or 39805 * extension against this list. This is a comma separated list of mime
39806 * types or file extensions. 39807 * 39808 * Eg.: `image/*,application/pdf,.psd` 39809 * 39810 * If the Dropzone is `clickable` this option will also be used as 39811 * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept) 39812 * parameter on the hidden file input as well. 39813 */ 39814 acceptedFiles: null, 39815 39816 /** 39817 * **Deprecated!** 39818 * Use acceptedFiles instead. 39819 */ 39820 acceptedMimeTypes: null, 39821 39822 /** 39823 * If false, files will be added to the queue but the queue will not be 39824 * processed automatically. 39825 * This can be useful if you need some additional user input before sending 39826 * files (or if you want want all files sent at once). 39827 * If you're ready to send the file simply call `myDropzone.processQueue()`. 39828 * 39829 * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation 39830 * section for more information. 39831 */ 39832 autoProcessQueue: true, 39833 39834 /** 39835 * If false, files added to the dropzone will not be queued by default. 39836 * You'll have to call `enqueueFile(file)` manually. 39837 */ 39838 autoQueue: true, 39839 39840 /** 39841 * If `true`, this will add a link to every file preview to remove or cancel (if 39842 * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation` 39843 * and `dictRemoveFile` options are used for the wording. 39844 */ 39845 addRemoveLinks: false, 39846 39847 /** 39848 * Defines where to display the file previews â if `null` the 39849 * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS 39850 * selector. The element should have the `dropzone-previews` class so 39851 * the previews are displayed properly. 39852 */ 39853 previewsContainer: null, 39854 39855 /** 39856 * This is the element the hidden input field (which is used when clicking on the 39857 * dropzone to trigger file selection) will be appended to. This might 39858 * be important in case you use frameworks to switch the content of your page. 39859 * 39860 * Can be a selector string, or an element directly. 39861 */ 39862 hiddenInputContainer: "body", 39863 39864 /** 39865 * If null, no capture type will be specified 39866 * If camera, mobile devices will skip the file selection and choose camera 39867 * If microphone, mobile devices will skip the file selection and choose the microphone 39868 * If camcorder, mobile devices will skip the file selection and choose the camera in video mode 39869 * On apple devices multiple must be set to false. AcceptedFiles may need to 39870 * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*"). 39871 */ 39872 capture: null, 39873 39874 /** 39875 * **Deprecated**. Use `renameFile` instead. 39876 */ 39877 renameFilename: null, 39878 39879 /** 39880 * A function that is invoked before the file is uploaded to the server and renames the file. 39881 * This function gets the `File` as argument and can use the `file.name`. The actual name of the 39882 * file that gets used during the upload can be accessed through `file.upload.filename`. 39883 */ 39884 renameFile: null, 39885 39886 /** 39887 * If `true` the fallback will be forced. This is very useful to test your server 39888 * implementations first and make sure that everything works as 39889 * expected without dropzone if you experience problems, and to test 39890 * how your fallbacks will look. 39891 */ 39892 forceFallback: false, 39893 39894 /** 39895 * The text used before any files are dropped. 39896 */ 39897 dictDefaultMessage: "Drop files here to upload", 39898 39899 /** 39900 * The text that replaces the default message text it the browser is not supported. 39901 */ 39902 dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", 39903 39904 /** 39905 * The text that will be added before the fallback form. 39906 * If you provide a fallback element yourself, or if this option is `null` this will 39907 * be ignored. 39908 */ 39909 dictFallbackText: "Please use the fallback form below to upload your files like in the olde
39909n days.", 39910 39911 /** 39912 * If the filesize is too big. 39913 * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values. 39914 */ 39915 dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", 39916 39917 /** 39918 * If the file doesn't match the file type. 39919 */ 39920 dictInvalidFileType: "You can't upload files of this type.", 39921 39922 /** 39923 * If the server response was invalid. 39924 * `{{statusCode}}` will be replaced with the servers status code. 39925 */ 39926 dictResponseError: "Server responded with {{statusCode}} code.", 39927 39928 /** 39929 * If `addRemoveLinks` is true, the text to be used for the cancel upload link. 39930 */ 39931 dictCancelUpload: "Cancel upload", 39932 39933 /** 39934 * The text that is displayed if an upload was manually canceled 39935 */ 39936 dictUploadCanceled: "Upload canceled.", 39937 39938 /** 39939 * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload. 39940 */ 39941 dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", 39942 39943 /** 39944 * If `addRemoveLinks` is true, the text to be used to remove a file. 39945 */ 39946 dictRemoveFile: "Remove file", 39947 39948 /** 39949 * If this is not null, then the user will be prompted before removing a file. 39950 */ 39951 dictRemoveFileConfirmation: null, 39952 39953 /** 39954 * Displayed if `maxFiles` is st and exceeded. 39955 * The string `{{maxFiles}}` will be replaced by the configuration value. 39956 */ 39957 dictMaxFilesExceeded: "You can not upload any more files.", 39958 39959 /** 39960 * Allows you to translate the different units. Starting with `tb` for terabytes and going down to 39961 * `b` for bytes. 39962 */ 39963 dictFileSizeUnits: { tb: "TB", gb: "GB", mb: "MB", kb: "KB", b: "b" }, 39964 /** 39965 * Called when dropzone initialized 39966 * You can add event listeners here 39967 */ 39968 init: function init() {}, 39969 39970 39971 /** 39972 * Can be an **object** of additional parameters to transfer to the server, **or** a `Function` 39973 * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case 39974 * of a function, this needs to return a map. 39975 * 39976 * The default implementation does nothing for normal uploads, but adds relevant information for 39977 * chunked uploads. 39978 * 39979 * This is the same as adding hidden input fields in the form element. 39980 */ 39981 params: function params(files, xhr, chunk) { 39982 if (chunk) { 39983 return { 39984 dzuuid: chunk.file.upload.uuid, 39985 dzchunkindex: chunk.index, 39986 dztotalfilesize: chunk.file.size, 39987 dzchunksize: this.options.chunkSize, 39988 dztotalchunkcount: chunk.file.upload.totalChunkCount, 39989 dzchunkbyteoffset: chunk.index * this.options.chunkSize 39990 }; 39991 } 39992 }, 39993 39994 39995 /** 39996 * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File) 39997 * and a `done` function as parameters. 39998 * 39999 * If the done function is invoked without arguments, the file is "accepted" and will 40000 * be processed. If you pass an error message, the file is rejected, and the error 40001 * message will be displayed. 40002 * This function will not be called if the file is too big or doesn't match the mime types. 40003 */ 40004 accept: function accept(file, done) { 40005 return done(); 40006 }, 40007 40008 40009 /** 40010 * The callback that will be invoked when all chunks have been uploaded for a file. 40011 * It gets the file for which the chunks have been uploaded as the first parameter, 40012 * and the `done` function as second. `done()` needs to be invoked when everything 40013 * needed to finish the upload process is done. 40014 */ 40015 chunksUploaded: function chunksUploaded(file, done) { 40016 done(); 40017 }, 40018 40019 /** 40020 * Gets called when the browser is not supported. 40021 * The default implementation shows the fallback input field and adds 40022 * a text. 40023 */ 40024 fallback: function fallback() { 40025 // This code should pass in IE7... :( 40026 var messageElement = void 0; 40027 this.element.className = this.element.className + " dz-browser-not-supported"; 40028 40029 for (var _iterator2 = this.element.getElementsByTagName("div"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 40030 var _ref2; 40031 40032 if (_isArray2) { 40033 if (_i2 >= _iterator2.length) break; 40034 _ref2 = _iterator2[_i2++]; 40035 } else { 40036 _i2 = _iterator2.next(); 40037 if (_i2.done) break; 40038 _ref2 = _i2.value; 40039 } 40040 40041 var child = _ref2; 40042 40043 if (/(^| )dz-message($| )/.test(child.className)) { 40044 messageElement = child; 40045 child.className = "dz-message"; // Removes the 'dz-default' class 40046 break; 40047 } 40048 } 40049 if (!messageElement) { 40050 messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>"); 40051 this.element.appendChild(messageElement); 40052 } 40053 40054 var span = messageElement.getElementsByTagName("span")[0]; 40055 if (span) { 40056 if (span.textContent != null) { 40057 span.textContent = this.options.dictFallbackMessage; 40058 }
40058 else if (span.innerText != null) { 40059 span.innerText = this.options.dictFallbackMessage; 40060 } 40061 } 40062 40063 return this.element.appendChild(this.getFallbackForm()); 40064 }, 40065 40066 40067 /** 40068 * Gets called to calculate the thumbnail dimensions. 40069 * 40070 * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing: 40071 * 40072 * - `srcWidth` & `srcHeight` (required) 40073 * - `trgWidth` & `trgHeight` (required) 40074 * - `srcX` & `srcY` (optional, default `0`) 40075 * - `trgX` & `trgY` (optional, default `0`) 40076 * 40077 * Those values are going to be used by `ctx.drawImage()`. 40078 */ 40079 resize: function resize(file, width, height, resizeMethod) { 40080 var info = { 40081 srcX: 0, 40082 srcY: 0, 40083 srcWidth: file.width, 40084 srcHeight: file.height 40085 }; 40086 40087 var srcRatio = file.width / file.height; 40088 40089 // Automatically calculate dimensions if not specified 40090 if (width == null && height == null) { 40091 width = info.srcWidth; 40092 height = info.srcHeight; 40093 } else if (width == null) { 40094 width = height * srcRatio; 40095 } else if (height == null) { 40096 height = width / srcRatio; 40097 } 40098 40099 // Make sure images aren't upscaled 40100 width = Math.min(width, info.srcWidth); 40101 height = Math.min(height, info.srcHeight); 40102 40103 var trgRatio = width / height; 40104 40105 if (info.srcWidth > width || info.srcHeight > height) { 40106 // Image is bigger and needs rescaling 40107 if (resizeMethod === 'crop') { 40108 if (srcRatio > trgRatio) { 40109 info.srcHeight = file.height; 40110 info.srcWidth = info.srcHeight * trgRatio; 40111 } else { 40112 info.srcWidth = file.width; 40113 info.srcHeight = info.srcWidth / trgRatio; 40114 } 40115 } else if (resizeMethod === 'contain') { 40116 // Method 'contain' 40117 if (srcRatio > trgRatio) { 40118 height = width / srcRatio; 40119 } else { 40120 width = height * srcRatio; 40121 } 40122 } else { 40123 throw new Error("Unknown resizeMethod '" + resizeMethod + "'"); 40124 } 40125 } 40126 40127 info.srcX = (file.width - info.srcWidth) / 2; 40128 info.srcY = (file.height - info.srcHeight) / 2; 40129 40130 info.trgWidth = width; 40131 info.trgHeight = height; 40132 40133 return info; 40134 }, 40135 40136 40137 /** 40138 * Can be used to transform the file (for example, resize an image if necessary). 40139 * 40140 * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes 40141 * images according to those dimensions. 40142 * 40143 * Gets the `file` as the first parameter, and a `done()` function as the second, that needs 40144 * to be invoked with the file when the transformation is done. 40145 */ 40146 transformFile: function transformFile(file, done) { 40147 if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) { 40148 return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done); 40149 } else { 40150 return done(file); 40151 } 40152 }, 40153 40154 40155 /** 40156 * A string that contains the template used for each dropped 40157 * file. Change it to fulfill your needs but make sure to properly 40158 * provide all elements. 40159 * 40160 * If you want to use an actual HTML element instead of providing a String 40161 * as a config option, you could create a div with the id `tpl`, 40162 * put the template inside it and provide the element like this: 40163 * 40164 * document 40165 * .querySelector('#tpl') 40166 * .innerHTML 40167 * 40168 */ 40169 previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n <div class=\"dz-details\">\n <div class=\"dz-size\"><span data-dz-size></span></div>\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n </div>\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n <div class=\"dz-success-mark\">\n <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n <title>Check</title>\n <defs></defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n </g>\n </svg>\n </div>\n <div class=\"dz-error-mark\">\n <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n <title>Error</title>\n <defs></defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n </g>\n </g>\n </svg>\n </div>\n</div>", 40170 40171 // END OPTIONS 40172 // (Required by the dropzone documentation parser) 40173 40174 40175 /* 40176 Those functions register themselves to the events on init and handle all 40177 the user interface specific stuff. Overwriting them won't break the upload 40178 but can break the way it's displayed. 40179 You can overwrite them if you don't like the default behavior. If you just 40180 want to add an additional event handler, register it on the dropzone object 40181 and don't overwrite those options. 40182 */ 40183 40184 // Those are self explanatory and simply concern the DragnDrop. 40185 drop: function drop(e) { 40186 return this.element.classList.remove("dz-drag-hover"); 40187 }, 40188 dragstart: function dragstart(e) {}, 40189 dragend: function dragend(e) { 40190 return this.element.classList.remove("dz-drag-hover"); 40191 }, 40192 dragenter: function dragenter(e) { 40193 return this.element.classList.add("dz-drag-hover"); 40194 }, 40195 dragover: function dragover(e) { 40196 return this.element.classList.add("dz-drag-hover"); 40197 }, 40198 dragleave: function dragleave(e) { 40199 return this.element.classList.remove("dz-drag-hover"); 40200 }, 40201 paste: function paste(e) {}, 40202 40203 40204 // Called whenever there are no files left in the dropzone anymore, and the 40205 // dropzone should be displayed as if in the initial state. 40206 reset: function reset() { 40207 return this.element.classList.remove("dz-started"); 40208 }, 40209 40210 40211 // Called when a file is added to the queue 40212 // Receives `file` 40213 addedfile: function addedfile(file) { 40214 var _this2 = this; 40215 40216 if (this.element === this.previewsContainer) { 40217 this.element.classList.add("dz-started"); 40218 } 40219 40220 if (this.previewsContainer) { 40221 file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); 40222 file.previewTemplate = file.previewElement; // Backwards compatibility 40223 40224 this.previewsContainer.appendChild(file.previewElement); 40225 for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { 40226 var _ref3; 40227 40228 if (_isArray3) { 40229 if (_i3 >= _iterator3.length) break; 40230 _ref3 = _iterator3[_i3++]; 40231 } else { 40232 _i3 = _iterator3.next(); 40233 if (_i3.done) break; 40234 _ref3 = _i3.value; 40235 } 40236 40237 var node = _ref3; 40238 40239 node.textContent = file.name; 40240 } 40241 for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { 40242 if (_isArray4) { 40243 if (_i4 >= _iterator4.length) break; 40244 node = _iterator4[_i4++]; 40245 } else { 40246 _i4 = _iterator4.next(); 40247 if (_i4.done) break; 40248 node = _i4.value; 40249 } 40250 40251 node.innerHTML = this.filesize(file.size); 40252 } 40253 40254 if (this.options.addRemoveLinks) { 40255 file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>"); 40256 file.previewElement.appendChild(file._removeLink); 40257 } 40258 40259 var removeFileEvent = function removeFileEvent(e) { 40260 e.preventDefault(); 40261 e.stopPropagation(); 40262 if (file.status === Dropzone.UPLOADING) { 40263 return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () { 40264 return _this2.removeFile(file); 40265 }); 40266 } else { 40267 if (_this2.options.dictRemoveFileConfirmation) { 40268 return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () { 40269 return _this2.removeFile(file); 40270 }); 40271 } else { 40272 return _this2.removeFile(file); 40273 } 40274 } 40275 }; 40276 40277 for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { 40278 var _ref4; 40279 40280 if (_isArray5) { 40281 if (_i5 >= _iterator5.length) break; 40282 _ref4 = _iterator5[_i5++]; 40283 } else { 40284 _i5 = _iterator5.next(); 40285 if (_i5.done) break; 40286 _ref4 = _i5.value; 40287 } 40288 40289 var removeLink = _ref4; 40290 40291 removeLink.addEventListener("click", removeFileEvent); 40292 } 40293 } 40294 }, 40295 40296 40297 // Called whenever a file is removed. 40298 removedfile: function removedfile(file) { 40299 if (file.previewElement != null && file.previewElement.parentNode != null) { 40300 file.previewElement.parentNode.removeChild(file.previewElement); 40301 } 40302 return this._updateMaxFilesReachedClass(); 40303 }, 40304 40305 40306 // Called when a thumbnail has been generated 40307 // Receives `file` and `dataUrl` 40308 thumbnail: function thumbnail(file, dataUrl) { 40309 if (file.previewElement) { 40310 file.previewElement.classList.remove("dz-file-preview"); 40311 for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { 40312 var _ref5; 40313 40314 if (_isArray6) { 40315 if (_i6 >= _iterator6.length) break; 40316 _ref5 = _iterator6[_i6++]; 40317 } else { 40318 _i6 = _iterator6.next(); 40319 if (_i6.done) break; 40320 _ref5 = _i6.value; 40321 } 40322 40323 var thumbnailElement = _ref5; 40324 40325 thumbnailElement.alt = file.name; 40326 thumbnailElement.src = dataUrl; 40327 } 40328 40329 return setTimeout(function () { 40330 return file.previewElement.classList.add("dz-image-preview"); 40331 }, 1); 40332 } 40333 }, 40334 40335 40336 // Called whenever an error occurs 40337 // Receives `file` and `message` 40338 error: function error(file, message) { 40339 if (file.previewElement) { 40340 file.previewElement.classList.add("dz-error"); 40341 if (typeof message !== "String" && message.error) { 40342 message = message.error; 40343 } 40344 for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { 40345 var _ref6; 40346 40347 if (_isArray7) { 40348 if (_i7 >= _iterator7.length) break; 40349 _ref6 = _iterator7[_i7++]; 40350 } else { 40351 _i7 = _iterator7.next(); 40352 if (_i7.done) break; 40353 _ref6 = _i7.value; 40354 } 40355 40356 var node = _ref6; 40357 40358 node.textContent = message; 40359 } 40360 } 40361 }, 40362 errormultiple: function errormultiple() {}, 40363 40364 40365 // Called when a file gets processed. Since there is a cue, not all added 40366 // files are processed immediately. 40367 // Receives `file` 40368 processing: function processing(file) { 40369 if (file.previewElement) { 40370 file.previewElement.classList.add("dz-processing"); 40371 if (file._removeLink) { 40372 return file._removeLink.innerHTML = this.options.dictCancelUpload; 40373 } 40374 } 40375 }, 40376 processingmultiple: function processingmultiple() {}, 40377 40378 40379 // Called whenever the upload progress gets updated. 40380 // Receives `file`, `progress` (percentage 0-100) and `bytesSent`. 40381 // To get the total number of bytes of the file, use `file.size` 40382 uploadprogress: function uploadprogress(file, progress, bytesSent) { 40383 if (file.previewElement) { 40384 for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { 40385 var _ref7; 40386 40387 if (_isArray8) { 40388 if (_i8 >= _iterator8.length) break; 40389 _ref7 = _iterator8[_i8++]; 40390 } else { 40391 _i8 = _iterator8.next(); 40392 if (_i8.done) break; 40393 _ref7 = _i8.value; 40394 } 40395 40396 var node = _ref7; 40397 40398 node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + "%"; 40399 } 40400 } 40401 }, 40402 40403 40404 // Called whenever the total upload progress gets updated. 40405 // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent 40406 totaluploadprogress: function totaluploadprogress() {}, 40407 40408 40409 // Called just before the file is sent. Get
40409s the `xhr` object as second 40410 // parameter, so you can modify it (for example to add a CSRF token) and a 40411 // `formData` object to add additional information. 40412 sending: function sending() {}, 40413 sendingmultiple: function sendingmultiple() {}, 40414 40415 40416 // When the complete upload is finished and successful 40417 // Receives `file` 40418 success: function success(file) { 40419 if (file.previewElement) { 40420 return file.previewElement.classList.add("dz-success"); 40421 } 40422 }, 40423 successmultiple: function successmultiple() {}, 40424 40425 40426 // When the upload is canceled. 40427 canceled: function canceled(file) { 40428 return this.emit("error", file, this.options.dictUploadCanceled); 40429 }, 40430 canceledmultiple: function canceledmultiple() {}, 40431 40432 40433 // When the upload is finished, either with success or an error. 40434 // Receives `file` 40435 complete: function complete(file) { 40436 if (file._removeLink) { 40437 file._removeLink.innerHTML = this.options.dictRemoveFile; 40438 } 40439 if (file.previewElement) { 40440 return file.previewElement.classList.add("dz-complete"); 40441 } 40442 }, 40443 completemultiple: function completemultiple() {}, 40444 maxfilesexceeded: function maxfilesexceeded() {}, 40445 maxfilesreached: function maxfilesreached() {}, 40446 queuecomplete: function queuecomplete() {}, 40447 addedfiles: function addedfiles() {} 40448 }; 40449 40450 this.prototype._thumbnailQueue = []; 40451 this.prototype._processingThumbnail = false; 40452 } 40453 40454 // global utility 40455 40456 }, { 40457 key: "extend", 40458 value: function extend(target) { 40459 for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 40460 objects[_key2 - 1] = arguments[_key2]; 40461 } 40462 40463 for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { 40464 var _ref8; 40465 40466 if (_isArray9) { 40467 if (_i9 >= _iterator9.length) break; 40468 _ref8 = _iterator9[_i9++]; 40469 } else { 40470 _i9 = _iterator9.next(); 40471 if (_i9.done) break; 40472 _ref8 = _i9.value; 40473 } 40474 40475 var object = _ref8; 40476 40477 for (var key in object) { 40478 var val = object[key]; 40479 target[key] = val; 40480 } 40481 } 40482 return target; 40483 } 40484 }]); 40485 40486 function Dropzone(el, options) { 40487 _classCallCheck(this, Dropzone); 40488 40489 var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this)); 40490 40491 var fallback = void 0, 40492 left = void 0; 40493 _this.element = el; 40494 // For backwards compatibility since the version was in the prototype previously 40495 _this.version = Dropzone.version; 40496 40497 _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, ""); 40498 40499 _this.clickableElements = []; 40500 _this.listeners = []; 40501 _this.files = []; // All files 40502 40503 if (typeof _this.element === "string") { 40504 _this.element = document.querySelector(_this.element); 40505 } 40506 40507 // Not checking if instance of HTMLElement or Element since IE9 is extremely weird. 40508 if (!_this.element || _this.element.nodeType == null) { 40509 throw new Error("Invalid dropzone element."); 40510 } 40511 40512 if (_this.element.dropzone) { 40513 throw new Error("Dropzone already attached."); 40514 } 40515 40516 // Now add this dropzone to the instances. 40517 Dropzone.instances.push(_this); 40518 40519 // Put the dropzone inside the element itself. 40520 _this.element.dropzone = _this; 40521 40522 var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {}; 40523 40524 _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {}); 40525 40526 // If the browser failed, just call the fallback and leave 40527 if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) { 40528 var _ret; 40529 40530 return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret); 40531 } 40532 40533 // @options.url = @element.getAttribute "action" unless @options.url? 40534 if (_this.options.url == null) { 40535 _this.options.url = _this.element.getAttribute("action"); 40536 } 40537 40538 if (!_this.options.url) { 40539 throw new Error("No URL provided."); 40540 } 40541 40542 if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) { 40543 throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); 40544 } 40545 40546 if (_this.options.uploadMultiple && _this.options.chunking) { 40547 throw new Error('You cannot set both: uploadMultiple and chunking.'); 40548 } 40549 40550 // Backwards compatibility 40551 if (_this.options.acceptedMimeTypes) { 40552 _this.options.acceptedFiles = _this.options.acceptedMimeTypes; 40553 delete _this.options.acceptedMimeTypes; 40554 } 40555 40556 // Backwards compatibility 40557 if (_this.options.renameFilename != null) { 40558 _this.options.renameFile = function (file) { 40559 return _this.options.renameFilename.call(_this, file.name, file); 40560 }; 40561 } 40562 40563 _this.options.method = _this.options.method.toUpperCase(); 40564 40565 if ((fallback = _this.getExistingFallback()) && fallback.parentNode) { 40566 // Remove the fallback 40567 fallback.parentNode.removeChild(fallback); 40568 } 40569 40570 // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false 40571 if (_this.options.previewsContainer !== false) { 40572 if (_this.options.previewsContainer) { 40573 _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer"); 40574 } else { 40575 _this.previewsContainer = _this.element; 40576 } 40577 } 40578 40579 if (_this.options.clickable) { 40580 if (_this.options.clickable === true) { 40581 _this.clickableElements = [_this.element]; 40582 } else { 40583 _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable"); 40584 } 40585 } 40586 40587 _this.init(); 40588 return _this; 40589 } 40590 40591 // Returns all files that have been accepted 40592 40593 40594 _createClass(Dropzone, [{ 40595 key: "getAcceptedFiles", 40596 value: function getAcceptedFiles() { 40597 return this.files.filter(function (file) { 40598 return file.accepted; 40599 }).map(function (file) { 40600 return file; 40601 }); 40602 } 40603 40604 // Returns all files that have been rejected
40605 // Not sure when that's going to be useful, but added for completeness. 40606 40607 }, { 40608 key: "getRejectedFiles", 40609 value: function getRejectedFiles() { 40610 return this.files.filter(function (file) { 40611 return !file.accepted; 40612 }).map(function (file) { 40613 return file; 40614 }); 40615 } 40616 }, { 40617 key: "getFilesWithStatus", 40618 value: function getFilesWithStatus(status) { 40619 return this.files.filter(function (file) { 40620 return file.status === status; 40621 }).map(function (file) { 40622 return file; 40623 }); 40624 } 40625 40626 // Returns all files that are in the queue 40627 40628 }, { 40629 key: "getQueuedFiles", 40630 value: function getQueuedFiles() { 40631 return this.getFilesWithStatus(Dropzone.QUEUED); 40632 } 40633 }, { 40634 key: "getUploadingFiles", 40635 value: function getUploadingFiles() { 40636 return this.getFilesWithStatus(Dropzone.UPLOADING); 40637 } 40638 }, { 40639 key: "getAddedFiles", 40640 value: function getAddedFiles() { 40641 return this.getFilesWithStatus(Dropzone.ADDED); 40642 } 40643 40644 // Files that are either queued or uploading 40645 40646 }, { 40647 key: "getActiveFiles", 40648 value: function getActiveFiles() { 40649 return this.files.filter(function (file) { 40650 return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED; 40651 }).map(function (file) { 40652 return file; 40653 }); 40654 } 40655 40656 // The function that gets called when Dropzone is initialized. You 40657 // can (and should) setup event listeners inside this function. 40658 40659 }, { 40660 key: "init", 40661 value: function init() { 40662 var _this3 = this; 40663 40664 // In case it isn't set already 40665 if (this.element.tagName === "form") { 40666 this.element.setAttribute("enctype", "multipart/form-data"); 40667 } 40668 40669 if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { 40670 this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>")); 40671 } 40672 40673 if (this.clickableElements.length) { 40674 var setupHiddenFileInput = function setupHiddenFileInput() { 40675 if (_this3.hiddenFileInput) { 40676 _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput); 40677 } 40678 _this3.hiddenFileInput = document.createElement("input"); 40679 _this3.hiddenFileInput.setAttribute("type", "file"); 40680 if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) { 40681 _this3.hiddenFileInput.setAttribute("multiple", "multiple"); 40682 } 40683 _this3.hiddenFileInput.className = "dz-hidden-input"; 40684 40685 if (_this3.options.acceptedFiles !== null) { 40686 _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles); 40687 } 40688 if (_this3.options.capture !== null) { 40689 _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture); 40690 } 40691 40692 // Not setting `display="none"` because some browsers don't accept clicks 40693 // on elements that aren't displayed. 40694 _this3.hiddenFileInput.style.visibility = "hidden"; 40695 _this3.hiddenFileInput.style.position = "absolute"; 40696 _this3.hiddenFileInput.style.top = "0"; 40697 _this3.hiddenFileInput.style.left = "0"; 40698 _this3.hiddenFileInput.style.height = "0"; 40699 _this3.hiddenFileInput.style.width = "0"; 40700 Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput); 40701 return _this3.hiddenFileInput.addEventListener("change", function () { 40702 var files = _this3.hiddenFileInput.files; 40703 40704 if (files.length) { 40705 for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { 40706 var _ref9; 40707 40708 if (_isArray10) { 40709 if (_i10 >= _iterator10.length) break; 40710 _ref9 = _iterator10[_i10++]; 40711 } else { 40712 _i10 = _iterator10.next(); 40713 if (_i10.done) break; 40714 _ref9 = _i10.value; 40715 } 40716 40717 var file = _ref9; 40718 40719 _this3.addFile(file); 40720 } 40721 } 40722 _this3.emit("addedfiles", files); 40723 return setupHiddenFileInput(); 40724 }); 40725 }; 40726 setupHiddenFileInput(); 40727 } 40728 40729 this.URL = window.URL !== null ? window.URL : window.webkitURL; 40730 40731 // Setup all event listeners on the Dropzone object itself. 40732 // They're not in @setupEventListeners() because they shouldn't be removed 40733 // again when the dropzone gets disabled. 40734 for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) { 40735 var _ref10; 40736 40737 if (_isArray11) { 40738 if (_i11 >= _iterator11.length) break; 40739 _ref10 = _iterator11[_i11++]; 40740 } else { 40741 _i11 = _iterator11.next(); 40742 if (_i11.done) break; 40743 _ref10 = _i11.value; 40744 } 40745 40746 var eventName = _ref10; 40747 40748 this.on(eventName, this.options[eventName]); 40749 } 40750 40751 this.on("uploadprogress", function () { 40752 return _this3.updateTotalUploadProgress(); 40753 }); 40754 40755 this.on("removedfile", function () { 40756 return _this3.updateTotalUploadProgress(); 40757 }); 40758 40759 this.on("canceled", function (file) { 40760 return _this3.emit("complete", file); 40761 }); 40762 40763 // Emit a `queuecomplete` event if all files finished uploading. 40764 this.on("complete", function (file) { 40765 if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) { 40766 // This needs to be deferred so that `queuecomplete` really triggers after `complete` 40767 return setTimeout(function () { 40768 return _this3.emit("queuecomplete"); 40769 }, 0); 40770 } 40771 }); 40772 40773 var noPropagation = function noPropagation(e) { 40774 e.stopPropagation(); 40775 if (e.preventDefault) { 40776 return e.preventDefault(); 40777 } else { 40778 return e.returnValue = false;
40779 } 40780 }; 40781 40782 // Create the listeners 40783 this.listeners = [{ 40784 element: this.element, 40785 events: { 40786 "dragstart": function dragstart(e) { 40787 return _this3.emit("dragstart", e); 40788 }, 40789 "dragenter": function dragenter(e) { 40790 noPropagation(e); 40791 return _this3.emit("dragenter", e); 40792 }, 40793 "dragover": function dragover(e) { 40794 // Makes it possible to drag files from chrome's download bar 40795 // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar 40796 // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception) 40797 var efct = void 0; 40798 try { 40799 efct = e.dataTransfer.effectAllowed; 40800 } catch (error) {} 40801 e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; 40802 40803 noPropagation(e); 40804 return _this3.emit("dragover", e); 40805 }, 40806 "dragleave": function dragleave(e) { 40807 return _this3.emit("dragleave", e); 40808 }, 40809 "drop": function drop(e) { 40810 noPropagation(e); 40811 return _this3.drop(e); 40812 }, 40813 "dragend": function dragend(e) { 40814 return _this3.emit("dragend", e); 40815 } 40816 40817 // This is disabled right now, because the browsers don't implement it properly. 40818 // "paste": (e) => 40819 // noPropagation e 40820 // @paste e 40821 } }]; 40822 40823 this.clickableElements.forEach(function (clickableElement) { 40824 return _this3.listeners.push({ 40825 element: clickableElement, 40826 events: { 40827 "click": function click(evt) { 40828 // Only the actual dropzone or the message element should trigger file selection 40829 if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) { 40830 _this3.hiddenFileInput.click(); // Forward the click 40831 } 40832 return true; 40833 } 40834 } 40835 }); 40836 }); 40837 40838 this.enable(); 40839 40840 return this.options.init.call(this); 40841 } 40842 40843 // Not fully tested yet 40844 40845 }, { 40846 key: "destroy", 40847 value: function destroy() { 40848 this.disable(); 40849 this.removeAllFiles(true); 40850 if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) { 40851 this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); 40852 this.hiddenFileInput = null; 40853 } 40854 delete this.element.dropzone; 40855 return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); 40856 } 40857 }, { 40858 key: "updateTotalUploadProgress", 40859 value: function updateTotalUploadProgress() { 40860 var totalUploadProgress = void 0; 40861 var totalBytesSent = 0; 40862 var totalBytes = 0; 40863 40864 var activeFiles = this.getActiveFiles(); 40865 40866 if (activeFiles.length) { 40867 for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) { 40868 var _ref11; 40869 40870 if (_isArray12) { 40871 if (_i12 >= _iterator12.length) break; 40872 _ref11 = _iterator12[_i12++]; 40873 } else { 40874 _i12 = _iterator12.next(); 40875 if (_i12.done) break; 40876 _ref11 = _i12.value; 40877 } 40878 40879 var file = _ref11; 40880 40881 totalBytesSent += file.upload.bytesSent; 40882 totalBytes += file.upload.total; 40883 } 40884 totalUploadProgress = 100 * totalBytesSent / totalBytes; 40885 } else { 40886 totalUploadProgress = 100; 40887 } 40888 40889 return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); 40890 } 40891 40892 // @options.paramName can be a function taking one parameter rather than a string. 40893 // A parameter name for a file is obtained simply by calling this with an index number. 40894 40895 }, { 40896 key: "_getParamName", 40897 value: function _getParamName(n) { 40898 if (typeof this.options.paramName === "function") { 40899 return this.options.paramName(n); 40900 } else { 40901 return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : ""); 40902 } 40903 } 40904 40905 // If @options.renameFile is a function, 40906 // the function will be used to rename the file.name before appending it to the formData 40907 40908 }, { 40909 key: "_renameFile", 40910 value: function _renameFile(file) { 40911 if (typeof this.options.renameFile !== "function") { 40912 return file.name; 40913 } 40914 return this.options.renameFile(file); 40915 } 40916 40917 // Returns a form that can be used as fallback if the browser does not support DragnDrop 40918 // 40919 // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided. 40920 // This code has to pass in IE7 :( 40921 40922 }, { 40923 key: "getFallbackForm", 40924 value: function getFallbackForm() { 40925 var existingFallback = void 0, 40926 form = void 0; 40927 if (existingFallback = this.getExistingFallback()) { 40928 return existingFallback; 40929 } 40930 40931 var fieldsString = "<div class=\"dz-fallback\">"; 40932 if (this.options.dictFallbackText) { 40933 fieldsString += "<p>" + this.options.dictFallbackText + "</p>"; 40934 } 40935 fieldsString += "<input type=\"file\" name=\"" + this._getParamName(0) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : undefined) + " /><input type=\"submit\" value=\"Upload!\"></div>"; 40936 40937 var fields = Dropzone.createElement(fieldsString); 40938 if (this.element.tagName !== "FORM") { 40939 form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>"); 40940 form.appendChild(fields); 40941 } else { 40942 // Make sure that the enctype and method attributes are set properly 40943 this.element.setAttribute("enctype", "multipart/form-data"); 40944 this.element.setAttribute("method", this.options.method); 40945 } 40946 return form != null ? form : fields; 40947 } 40948 40949 // Returns the fallback elements if they exist already 40950 // 40951 // This code has to pass in IE7 :( 40952 40953 }, { 40954 key: "getExistingFallback", 40955 value: function getExistingFallback() { 40956 var getFallback = function getFallback(elements) { 40957 for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) { 40958 var _ref12; 40959 40960 if (_isArray13) { 40961 if (_i13 >= _iterator13.length) break; 40962 _ref12 = _iterator13[_i13++]; 40963 } else { 40964 _i13 = _iterator13.next(); 40965 if (_i13.done) break; 40966 _ref12 = _i13.value; 40967 } 40968 40969 var el = _ref12; 40970 40971 if (/(^| )fallback($| )/.test(el.className)) { 40972 return el; 40973 } 40974 } 40975 }; 40976 40977 var _arr = ["div", "form"]; 40978 for (var _i14 = 0; _i14 < _arr.length; _i14++) { 40979 var tagName = _arr[_i14]; 40980 var fallback; 40981 if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { 40982 return fallback; 40983 } 40984 } 40985 } 40986 40987 // Activates all listeners stored in @listeners 40988 40989 }, { 40990 key: "setupEventListeners", 40991 value: function setupEventListeners() { 40992 return this.listeners.map(function (elementListeners) { 40993 return function () { 40994 var result = []; 40995 for (var event in elementListeners.events) { 40996 var listener = elementListeners.events[event]; 40997 result.push(elementListeners.element.addEventListener(event, listener, false)); 40998 } 40999 return result; 41000 }(); 41001 }); 41002 } 41003 41004 // Deactivates all listeners stored in @listeners 41005 41006 }, { 41007 key: "removeEventListeners", 41008 value: function removeEventListeners() { 41009 return this.listeners.map(function (elementListeners) { 41010 return function () { 41011 var result = []; 41012 for (var event in elementListeners.events) { 41013 var listener = elementListeners.events[event]; 41014 result.push(elementListeners.element.removeEventListener(event, listener, false)); 41015 } 41016 return result; 41017 }(); 41018 }); 41019 } 41020 41021 // Removes all event listeners and cancels all files in the queue or being processed. 41022 41023 }, { 41024 key: "disable", 41025 value: function disable() { 41026 var _this4 = this; 41027
41028 this.clickableElements.forEach(function (element) { 41029 return element.classList.remove("dz-clickable"); 41030 }); 41031 this.removeEventListeners(); 41032 this.disabled = true; 41033 41034 return this.files.map(function (file) { 41035 return _this4.cancelUpload(file); 41036 }); 41037 } 41038 }, { 41039 key: "enable", 41040 value: function enable() { 41041 delete this.disabled; 41042 this.clickableElements.forEach(function (element) { 41043 return element.classList.add("dz-clickable"); 41044 }); 41045 return this.setupEventListeners(); 41046 } 41047 41048 // Returns a nicely formatted filesize 41049 41050 }, { 41051 key: "filesize", 41052 value: function filesize(size) { 41053 var selectedSize = 0; 41054 var selectedUnit = "b"; 41055 41056 if (size > 0) { 41057 var units = ['tb', 'gb', 'mb', 'kb', 'b']; 41058 41059 for (var i = 0; i < units.length; i++) { 41060 var unit = units[i]; 41061 var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10; 41062 41063 if (size >= cutoff) { 41064 selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i); 41065 selectedUnit = unit; 41066 break; 41067 } 41068 } 41069 41070 selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits 41071 } 41072 41073 return "<strong>" + selectedSize + "</strong> " + this.options.dictFileSizeUnits[selectedUnit]; 41074 } 41075 41076 // Adds or removes the `dz-max-files-reached` class from the form. 41077 41078 }, { 41079 key: "_updateMaxFilesReachedClass", 41080 value: function _updateMaxFilesReachedClass() { 41081 if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) { 41082 if (this.getAcceptedFiles().length === this.options.maxFiles) { 41083 this.emit('maxfilesreached', this.files); 41084 } 41085 return this.element.classList.add("dz-max-files-reached"); 41086 } else { 41087 return this.element.classList.remove("dz-max-files-reached"); 41088 } 41089 } 41090 }, { 41091 key: "drop", 41092 value: function drop(e) { 41093 if (!e.dataTransfer) { 41094 return; 41095 } 41096 this.emit("drop", e); 41097 41098 // Convert the FileList to an Array 41099 // This is necessary for IE11 41100 var files = []; 41101 for (var i = 0; i < e.dataTransfer.files.length; i++) { 41102 files[i] = e.dataTransfer.files[i]; 41103 } 41104 41105 this.emit("addedfiles", files); 41106 41107 // Even if it's a folder, files.length will contain the folders. 41108 if (files.length) { 41109 var items = e.dataTransfer.items; 41110 41111 if (items && items.length && items[0].webkitGetAsEntry != null) { 41112 // The browser supports dropping of folders, so handle items instead of files 41113 this._addFilesFromItems(items); 41114 } else { 41115 this.handleFiles(files); 41116 } 41117 } 41118 } 41119 }, { 41120 key: "paste", 41121 value: function paste(e) { 41122 if (__guard__(e != null ? e.clipboardData : undefined, function (x) { 41123 return x.items; 41124 }) == null) { 41125 return; 41126 } 41127 41128 this.emit("paste", e); 41129 var items = e.clipboardData.items; 41130 41131 41132 if (items.length) { 41133 return this._addFilesFromItems(items); 41134 } 41135 } 41136 }, { 41137 key: "handleFiles", 41138 value: function handleFiles(files) { 41139 for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) { 41140 var _ref13; 41141 41142 if (_isArray14) { 41143 if (_i15 >= _iterator14.length) break; 41144 _ref13 = _iterator14[_i15++]; 41145 } else { 41146 _i15 = _iterator14.next(); 41147 if (_i15.done) break; 41148 _ref13 = _i15.value; 41149 } 41150 41151 var file = _ref13; 41152 41153 this.addFile(file); 41154 } 41155 } 41156 41157 // When a folder is dropped (or files are pasted), items must be handled 41158 // instead of files. 41159 41160 }, { 41161 key: "_addFilesFromItems", 41162 value: function _addFilesFromItems(items) { 41163 var _this5 = this; 41164 41165 return function () { 41166 var result = []; 41167 for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) { 41168 var _ref14; 41169 41170 if (_isArray15) { 41171 if (_i16 >= _iterator15.length) break; 41172 _ref14 = _iterator15[_i16++]; 41173 } else { 41174 _i16 = _iterator15.next(); 41175 if (_i16.done) break; 41176 _ref14 = _i16.value; 41177 } 41178 41179 var item = _ref14; 41180 41181 var entry; 41182 if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) { 41183 if (entry.isFile) { 41184 result.push(_this5.addFile(item.getAsFile())); 41185 } else if (entry.isDirectory) { 41186 // Append all files from that directory to files 41187 result.push(_this5._addFilesFromDirectory(entry, entry.name)); 41188 } else { 41189 result.push(undefined); 41190 } 41191 } else if (item.getAsFile != null) { 41192 if (item.kind == null || item.kind === "file") { 41193 result.push(_this5.addFile(item.getAsFile())); 41194 } else { 41195 result.push(undefined); 41196 } 41197 } else { 41198 result.push(undefined); 41199 } 41200 } 41201 return result; 41202 }(); 41203 } 41204 41205 // Goes through the directory, and adds each file it finds recursively 41206 41207 }, { 41208 key: "_addFilesFromDirectory", 41209 value: function _addFilesFromDirectory(directory, path) { 41210 var _this6 = this; 41211 41212 var dirReader = directory.createReader(); 41213 41214 var errorHandler = function errorHandler(error) { 41215 return __guardMethod__(console, 'log', function (o) { 41216 return o.log(error); 41217 }); 41218 }; 41219 41220 var readEntries = function readEntries() { 41221 return dirReader.readEntries(function (entries) { 41222 if (entries.length > 0) { 41223 for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) { 41224 var _ref15; 41225 41226 if (_isArray16) { 41227 if (_i17 >= _iterator16.length) break; 41228 _ref15 = _iterator16[_i17++]; 41229 } else { 41230 _i17 = _iterator16.next(); 41231 if (_i17.done) break; 41232 _ref15 = _i17.value; 41233 } 41234 41235 var entry = _ref15; 41236 41237 if (entry.isFile) { 41238 entry.file(function (file) { 41239 if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { 41240 return; 41241 } 41242 file.fullPath = path + "/" + file.name; 41243 return _this6.addFile(file); 41244 }); 41245 } else if (entry.isDirectory) { 41246 _this6._addFilesFromDirectory(entry, path + "/" + entry.name); 41247 } 41248 } 41249 41250 // Recursively call readEntries() again, since browser only handle 41251 // the first 100 entries. 41252 // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries 41253 readEntries(); 41254 } 41255 return null; 41256 }, errorHandler); 41257 }; 41258 41259 return readEntries(); 41260 } 41261 41262 // If `done()` is called without argument the file is accepted 41263 // If you call it with an error message, the file is rejected 41264 // (This allows for asynchronous validation) 41265 // 41266 // This function checks the filesize, and if the file.type passes the 41267 // `acceptedFiles` check. 41268 41269 }, { 41270 key: "accept", 41271 value: function accept(file, done) { 41272 if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) { 41273 return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); 41274 } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { 41275 return done(this.options.dictInvalidFileType); 41276 } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) { 41277 done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
41278 return this.emit("maxfilesexceeded", file); 41279 } else { 41280 return this.options.accept.call(this, file, done); 41281 } 41282 } 41283 }, { 41284 key: "addFile", 41285 value: function addFile(file) { 41286 var _this7 = this; 41287 41288 file.upload = { 41289 uuid: Dropzone.uuidv4(), 41290 progress: 0, 41291 // Setting the total upload size to file.size for the beginning 41292 // It's actual different than the size to be transmitted. 41293 total: file.size, 41294 bytesSent: 0, 41295 filename: this._renameFile(file), 41296 chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize), 41297 totalChunkCount: Math.ceil(file.size / this.options.chunkSize) 41298 }; 41299 this.files.push(file); 41300 41301 file.status = Dropzone.ADDED; 41302 41303 this.emit("addedfile", file); 41304 41305 this._enqueueThumbnail(file); 41306 41307 return this.accept(file, function (error) { 41308 if (error) { 41309 file.accepted = false; 41310 _this7._errorProcessing([file], error); // Will set the file.status 41311 } else { 41312 file.accepted = true; 41313 if (_this7.options.autoQueue) { 41314 _this7.enqueueFile(file); 41315 } // Will set .accepted = true 41316 } 41317 return _this7._updateMaxFilesReachedClass(); 41318 }); 41319 } 41320 41321 // Wrapper for enqueueFile 41322 41323 }, { 41324 key: "enqueueFiles", 41325 value: function enqueueFiles(files) { 41326 for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) { 41327 var _ref16; 41328 41329 if (_isArray17) { 41330 if (_i18 >= _iterator17.length) break; 41331 _ref16 = _iterator17[_i18++]; 41332 } else { 41333 _i18 = _iterator17.next(); 41334 if (_i18.done) break; 41335 _ref16 = _i18.value; 41336 } 41337 41338 var file = _ref16; 41339 41340 this.enqueueFile(file); 41341 } 41342 return null; 41343 } 41344 }, { 41345 key: "enqueueFile", 41346 value: function enqueueFile(file) { 41347 var _this8 = this; 41348 41349 if (file.status === Dropzone.ADDED && file.accepted === true) { 41350 file.status = Dropzone.QUEUED; 41351 if (this.options.autoProcessQueue) { 41352 return setTimeout(function () { 41353 return _this8.processQueue(); 41354 }, 0); // Deferring the call 41355 } 41356 } else { 41357 throw new Error("This file can't be queued because it has already been processed or was rejected."); 41358 } 41359 } 41360 }, { 41361 key: "_enqueueThumbnail", 41362 value: function _enqueueThumbnail(file) { 41363 var _this9 = this; 41364 41365 if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { 41366 this._thumbnailQueue.push(file); 41367 return setTimeout(function () { 41368 return _this9._processThumbnailQueue(); 41369 }, 0); // Deferring the call 41370 } 41371 } 41372 }, { 41373 key: "_processThumbnailQueue", 41374 value: function _processThumbnailQueue() { 41375 var _this10 = this; 41376 41377 if (this._processingThumbnail || this._thumbnailQueue.length === 0) { 41378 return; 41379 } 41380 41381 this._processingThumbnail = true; 41382 var file = this._thumbnailQueue.shift(); 41383 return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) { 41384 _this10.emit("thumbnail", file, dataUrl); 41385 _this10._processingThumbnail = false; 41386 return _this10._processThumbnailQueue(); 41387 }); 41388 } 41389 41390 // Can be called by the user to remove a file 41391 41392 }, { 41393 key: "removeFile", 41394 value: function removeFile(file) { 41395 if (file.status === Dropzone.UPLOADING) { 41396 this.cancelUpload(file); 41397 } 41398 this.files = without(this.files, file); 41399 41400 this.emit("removedfile", file); 41401 if (this.files.length === 0) { 41402 return this.emit("reset"); 41403 } 41404 } 41405 41406 // Removes all files that aren't currently processed from the list 41407 41408 }, { 41409 key: "removeAllFiles", 41410 value: function removeAllFiles(cancelIfNecessary) { 41411 // Create a copy of files since removeFile() changes the @files array. 41412 if (cancelIfNecessary == null) { 41413 cancelIfNecessary = false;
41414 } 41415 for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) { 41416 var _ref17; 41417 41418 if (_isArray18) { 41419 if (_i19 >= _iterator18.length) break; 41420 _ref17 = _iterator18[_i19++]; 41421 } else { 41422 _i19 = _iterator18.next(); 41423 if (_i19.done) break; 41424 _ref17 = _i19.value; 41425 } 41426 41427 var file = _ref17; 41428 41429 if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { 41430 this.removeFile(file); 41431 } 41432 } 41433 return null; 41434 } 41435 41436 // Resizes an image before it gets sent to the server. This function is the default behavior of 41437 // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with 41438 // the resized blob. 41439 41440 }, { 41441 key: "resizeImage", 41442 value: function resizeImage(file, width, height, resizeMethod, callback) { 41443 var _this11 = this; 41444 41445 return this.createThumbnail(file, width, height, resizeMethod, true, function (dataUrl, canvas) { 41446 if (canvas == null) { 41447 // The image has not been resized 41448 return callback(file); 41449 } else { 41450 var resizeMimeType = _this11.options.resizeMimeType; 41451 41452 if (resizeMimeType == null) { 41453 resizeMimeType = file.type; 41454 } 41455 var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality); 41456 if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') { 41457 // Now add the original EXIF information 41458 resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL); 41459 } 41460 return callback(Dropzone.dataURItoBlob(resizedDataURL)); 41461 } 41462 }); 41463 } 41464 }, { 41465 key: "createThumbnail", 41466 value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) { 41467 var _this12 = this; 41468 41469 var fileReader = new FileReader(); 41470 41471 fileReader.onload = function () { 41472 41473 file.dataURL = fileReader.result; 41474 41475 // Don't bother creating a thumbnail for SVG images since they're vector 41476 if (file.type === "image/svg+xml") { 41477 if (callback != null) { 41478 callback(fileReader.result); 41479 } 41480 return; 41481 } 41482 41483 return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback); 41484 }; 41485 41486 return fileReader.readAsDataURL(file); 41487 } 41488 }, { 41489 key: "createThumbnailFromUrl", 41490 value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) { 41491 var _this13 = this; 41492 41493 // Not using `new Image` here because of a bug in latest Chrome versions. 41494 // See https://github.com/enyo/dropzone/pull/226 41495 var img = document.createElement("img"); 41496 41497 if (crossOrigin) { 41498 img.crossOrigin = crossOrigin; 41499 } 41500 41501 img.onload = function () { 41502 var loadExif = function loadExif(callback) { 41503 return callback(1); 41504 }; 41505 if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) { 41506 loadExif = function loadExif(callback) { 41507 return EXIF.getData(img, function () { 41508 return callback(EXIF.getTag(this, 'Orientation')); 41509 }); 41510 }; 41511 } 41512 41513 return loadExif(function (orientation) { 41514 file.width = img.width; 41515 file.height = img.height; 41516 41517 var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod); 41518 41519 var canvas = document.createElement("canvas"); 41520 var ctx = canvas.getContext("2d"); 41521 41522 canvas.width = resizeInfo.trgWidth; 41523 canvas.height = resizeInfo.trgHeight; 41524 41525 if (orientation > 4) { 41526 canvas.width = resizeInfo.trgHeight; 41527 canvas.height = resizeInfo.trgWidth; 41528 } 41529 41530 switch (orientation) { 41531 case 2: 41532 // horizontal flip 41533 ctx.translate(canvas.width, 0); 41534 ctx.scale(-1, 1); 41535 break; 41536 case 3: 41537 // 180° rotate left 41538 ctx.translate(canvas.width, canvas.height); 41539 ctx.rotate(Math.PI); 41540 break; 41541 case 4: 41542 // vertical flip 41543 ctx.translate(0, canvas.height); 41544 ctx.scale(1, -1); 41545 break; 41546 case 5: 41547 // vertical flip + 90 rotate right 41548 ctx.rotate(0.5 * Math.PI); 41549 ctx.scale(1, -1); 41550 break; 41551 case 6: 41552 // 90° rotate right 41553 ctx.rotate(0.5 * Math.PI); 41554 ctx.translate(0, -canvas.width); 41555 break; 41556 case 7: 41557 // horizontal flip + 90 rotate right 41558 ctx.rotate(0.5 * Math.PI); 41559 ctx.translate(canvas.height, -canvas.width); 41560 ctx.scale(-1, 1); 41561 break; 41562 case 8: 41563 // 90° rotate left 41564 ctx.rotate(-0.5 * Math.PI); 41565 ctx.translate(-canvas.height, 0); 41566 break; 41567 } 41568 41569 // This is a bugfix for iOS' scaling bug. 41570 drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); 41571 41572 var thumbnail = canvas.toDataURL("image/png"); 41573 41574 if (callback != null) {
41575 return callback(thumbnail, canvas); 41576 } 41577 }); 41578 }; 41579 41580 if (callback != null) { 41581 img.onerror = callback; 41582 } 41583 41584 return img.src = file.dataURL; 41585 } 41586 41587 // Goes through the queue and processes files if there aren't too many already. 41588 41589 }, { 41590 key: "processQueue", 41591 value: function processQueue() { 41592 var parallelUploads = this.options.parallelUploads; 41593 41594 var processingLength = this.getUploadingFiles().length; 41595 var i = processingLength; 41596 41597 // There are already at least as many files uploading than should be 41598 if (processingLength >= parallelUploads) { 41599 return; 41600 } 41601 41602 var queuedFiles = this.getQueuedFiles(); 41603 41604 if (!(queuedFiles.length > 0)) { 41605 return; 41606 } 41607 41608 if (this.options.uploadMultiple) { 41609 // The files should be uploaded in one request 41610 return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); 41611 } else { 41612 while (i < parallelUploads) { 41613 if (!queuedFiles.length) { 41614 return; 41615 } // Nothing left to process 41616 this.processFile(queuedFiles.shift()); 41617 i++; 41618 } 41619 } 41620 } 41621 41622 // Wrapper for `processFiles` 41623 41624 }, { 41625 key: "processFile", 41626 value: function processFile(file) { 41627 return this.processFiles([file]); 41628 } 41629 41630 // Loads the file, then calls finishedLoading() 41631 41632 }, { 41633 key: "processFiles", 41634 value: function processFiles(files) { 41635 for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) { 41636 var _ref18; 41637 41638 if (_isArray19) { 41639 if (_i20 >= _iterator19.length) break; 41640 _ref18 = _iterator19[_i20++]; 41641 } else { 41642 _i20 = _iterator19.next(); 41643 if (_i20.done) break; 41644 _ref18 = _i20.value; 41645 } 41646 41647 var file = _ref18; 41648 41649 file.processing = true; // Backwards compatibility 41650 file.status = Dropzone.UPLOADING; 41651 41652 this.emit("processing", file); 41653 } 41654 41655 if (this.options.uploadMultiple) { 41656 this.emit("processingmultiple", files); 41657 } 41658 41659 return this.uploadFiles(files); 41660 } 41661 }, { 41662 key: "_getFilesWithXhr", 41663 value: function _getFilesWithXhr(xhr) { 41664 var files = void 0; 41665 return files = this.files.filter(function (file) { 41666 return file.xhr === xhr; 41667 }).map(function (file) { 41668 return file; 41669 }); 41670 } 41671 41672 // Cancels the file upload and sets the status to CANCELED 41673 // **if** the file is actually being uploaded. 41674 // If it's still in the queue, the file is being removed from it and the status 41675 // set to CANCELED. 41676 41677 }, { 41678 key: "cancelUpload", 41679 value: function cancelUpload(file) { 41680 if (file.status === Dropzone.UPLOADING) { 41681 var groupedFiles = this._getFilesWithXhr(file.xhr); 41682 for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) { 41683 var _ref19; 41684 41685 if (_isArray20) { 41686 if (_i21 >= _iterator20.length) break; 41687 _ref19 = _iterator20[_i21++]; 41688 } else { 41689 _i21 = _iterator20.next(); 41690 if (_i21.done) break; 41691 _ref19 = _i21.value; 41692 } 41693 41694 var groupedFile = _ref19; 41695 41696 groupedFile.status = Dropzone.CANCELED; 41697 } 41698 if (typeof file.xhr !== 'undefined') { 41699 file.xhr.abort(); 41700 } 41701 for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) { 41702 var _ref20; 41703 41704 if (_isArray21) { 41705 if (_i22 >= _iterator21.length) break; 41706 _ref20 = _iterator21[_i22++]; 41707 } else { 41708 _i22 = _iterator21.next(); 41709 if (_i22.done) break; 41710 _ref20 = _i22.value; 41711 } 41712 41713 var _groupedFile = _ref20; 41714 41715 this.emit("canceled", _groupedFile); 41716 } 41717 if (this.options.uploadMultiple) { 41718 this.emit("canceledmultiple", groupedFiles); 41719 } 41720 } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) { 41721 file.status = Dropzone.CANCELED;
41722 this.emit("canceled", file); 41723 if (this.options.uploadMultiple) { 41724 this.emit("canceledmultiple", [file]); 41725 } 41726 } 41727 41728 if (this.options.autoProcessQueue) { 41729 return this.processQueue(); 41730 } 41731 } 41732 }, { 41733 key: "resolveOption", 41734 value: function resolveOption(option) { 41735 if (typeof option === 'function') { 41736 for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { 41737 args[_key3 - 1] = arguments[_key3]; 41738 } 41739 41740 return option.apply(this, args); 41741 } 41742 return option; 41743 } 41744 }, { 41745 key: "uploadFile", 41746 value: function uploadFile(file) { 41747 return this.uploadFiles([file]); 41748 } 41749 }, { 41750 key: "uploadFiles", 41751 value: function uploadFiles(files) { 41752 var _this14 = this; 41753 41754 this._transformFiles(files, function (transformedFiles) { 41755 if (files[0].upload.chunked) { 41756 // This file should be sent in chunks! 41757 41758 // If the chunking option is set, we **know** that there can only be **one** file, since 41759 // uploadMultiple is not allowed with this option. 41760 var file = files[0]; 41761 var transformedFile = transformedFiles[0]; 41762 var startedChunkCount = 0; 41763 41764 file.upload.chunks = []; 41765 41766 var handleNextChunk = function handleNextChunk() { 41767 var chunkIndex = 0; 41768 41769 // Find the next item in file.upload.chunks that is not defined yet. 41770 while (file.upload.chunks[chunkIndex] !== undefined) { 41771 chunkIndex++; 41772 } 41773 41774 // This means, that all chunks have already been started. 41775 if (chunkIndex >= file.upload.totalChunkCount) return; 41776 41777 startedChunkCount++; 41778 41779 var start = chunkIndex * _this14.options.chunkSize; 41780 var end = Math.min(start + _this14.options.chunkSize, file.size); 41781 41782 var dataBlock = { 41783 name: _this14._getParamName(0), 41784 data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end), 41785 filename: file.upload.filename, 41786 chunkIndex: chunkIndex 41787 }; 41788 41789 file.upload.chunks[chunkIndex] = { 41790 file: file, 41791 index: chunkIndex, 41792 dataBlock: dataBlock, // In case we want to retry. 41793 status: Dropzone.UPLOADING, 41794 progress: 0, 41795 retries: 0 // The number of times this block has been retried. 41796 }; 41797 41798 _this14._uploadData(files, [dataBlock]); 41799 }; 41800 41801 file.upload.finishedChunkUpload = function (chunk) { 41802 var allFinished = true; 41803 chunk.status = Dropzone.SUCCESS; 41804 41805 // Clear the data from the chunk 41806 chunk.dataBlock = null; 41807 // Leaving this reference to xhr intact here will cause memory leaks in some browsers 41808 chunk.xhr = null; 41809 41810 for (var i = 0; i < file.upload.totalChunkCount; i++) { 41811 if (file.upload.chunks[i] === undefined) { 41812 return handleNextChunk(); 41813 } 41814 if (file.upload.chunks[i].status !== Dropzone.SUCCESS) { 41815 allFinished = false; 41816 } 41817 } 41818 41819 if (allFinished) { 41820 _this14.options.chunksUploaded(file, function () { 41821 _this14._finished(files, '', null); 41822 }); 41823 } 41824 }; 41825 41826 if (_this14.options.parallelChunkUploads) { 41827 for (var i = 0; i < file.upload.totalChunkCount; i++) { 41828 handleNextChunk(); 41829 } 41830 } else { 41831 handleNextChunk(); 41832 } 41833 } else { 41834 var dataBlocks = []; 41835 for (var _i23 = 0; _i23 < files.length; _i23++) { 41836 dataBlocks[_i23] = { 41837 name: _this14._getParamName(_i23), 41838 data: transformedFiles[_i23], 41839 filename: files[_i23].upload.filename 41840 }; 41841 } 41842 _this14._uploadData(files, dataBlocks); 41843 } 41844 }); 41845 } 41846 41847 /// Returns the right chunk for given file and xhr 41848 41849 }, { 41850 key: "_getChunk", 41851 value: function _getChunk(file, xhr) { 41852 for (var i = 0; i < file.upload.totalChunkCount; i++) { 41853 if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) { 41854 return file.upload.chunks[i]; 41855 } 41856 } 41857 } 41858 41859 // This function actually uploads the file(s) to the server. 41860 // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed 41861 // files, or individual chunks for chunked upload). 41862 41863 }, { 41864 key: "_uploadData", 41865 value: function _uploadData(files, dataBlocks) { 41866 var _this15 = this; 41867 41868 var xhr = new XMLHttpRequest(); 41869 41870 // Put the xhr object in the file objects to be able to reference it later. 41871 for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) { 41872 var _ref21; 41873 41874 if (_isArray22) { 41875 if (_i24 >= _iterator22.length) break; 41876 _ref21 = _iterator22[_i24++]; 41877 } else { 41878 _i24 = _iterator22.next(); 41879 if (_i24.done) break; 41880 _ref21 = _i24.value; 41881 } 41882 41883 var file = _ref21; 41884 41885 file.xhr = xhr; 41886 } 41887 if (files[0].upload.chunked) { 41888 // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk 41889 files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr; 41890 } 41891 41892 var method = this.resolveOption(this.options.method, files); 41893 var url = this.resolveOption(this.options.url, files); 41894 xhr.open(method, url, true); 41895 41896 // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8 41897 xhr.timeout = this.resolveOption(this.options.timeout, files); 41898 41899 // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179 41900 xhr.withCredentials = !!this.options.withCredentials; 41901 41902 xhr.onload = function (e) { 41903 _this15._finishedUploading(files, xhr, e); 41904 }; 41905 41906 xhr.onerror = function () { 41907 _this15._handleUploadError(files, xhr); 41908 }; 41909 41910 // Some browsers do not have the .upload property 41911 var progressObj = xhr.upload != null ? xhr.upload : xhr; 41912 progressObj.onprogress = function (e) { 41913 return _this15._updateFilesUploadProgress(files, xhr, e); 41914 }; 41915 41916 var headers = { 41917 "Accept": "application/json", 41918 "Cache-Control": "no-cache", 41919 "X-Requested-With": "XMLHttpRequest" 41920 }; 41921 41922 if (this.options.headers) { 41923 Dropzone.extend(headers, this.options.headers); 41924 } 41925 41926 for (var headerName in headers) { 41927 var headerValue = headers[headerName]; 41928 if (headerValue) { 41929 xhr.setRequestHeader(headerName, headerValue); 41930 } 41931 } 41932 41933 var formData = new FormData(); 41934 41935 // Adding all @options parameters 41936 if (this.options.params) { 41937 var additionalParams = this.options.params; 41938 if (typeof additionalParams === 'function') { 41939 additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null); 41940 } 41941 41942 for (var key in additionalParams) { 41943 var value = additionalParams[key]; 41944 formData.append(key, value); 41945 } 41946 } 41947 41948 // Let the user add additional data if necessary
41949 for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) { 41950 var _ref22; 41951 41952 if (_isArray23) { 41953 if (_i25 >= _iterator23.length) break; 41954 _ref22 = _iterator23[_i25++]; 41955 } else { 41956 _i25 = _iterator23.next(); 41957 if (_i25.done) break; 41958 _ref22 = _i25.value; 41959 } 41960 41961 var _file = _ref22; 41962 41963 this.emit("sending", _file, xhr, formData); 41964 } 41965 if (this.options.uploadMultiple) { 41966 this.emit("sendingmultiple", files, xhr, formData); 41967 } 41968 41969 this._addFormElementData(formData); 41970 41971 // Finally add the files 41972 // Has to be last because some servers (eg: S3) expect the file to be the last parameter 41973 for (var i = 0; i < dataBlocks.length; i++) { 41974 var dataBlock = dataBlocks[i]; 41975 formData.append(dataBlock.name, dataBlock.data, dataBlock.filename); 41976 } 41977 41978 this.submitRequest(xhr, formData, files); 41979 } 41980 41981 // Transforms all files with this.options.transformFile and invokes done with the transformed files when done. 41982 41983 }, { 41984 key: "_transformFiles", 41985 value: function _transformFiles(files, done) { 41986 var _this16 = this; 41987 41988 var transformedFiles = []; 41989 // Clumsy way of handling asynchronous calls, until I get to add a proper Future library. 41990 var doneCounter = 0; 41991 41992 var _loop = function _loop(i) { 41993 _this16.options.transformFile.call(_this16, files[i], function (transformedFile) { 41994 transformedFiles[i] = transformedFile; 41995 if (++doneCounter === files.length) { 41996 done(transformedFiles); 41997 } 41998 }); 41999 }; 42000 42001 for (var i = 0; i < files.length; i++) { 42002 _loop(i); 42003 } 42004 } 42005 42006 // Takes care of adding other input elements of the form to the AJAX request 42007 42008 }, { 42009 key: "_addFormElementData", 42010 value: function _addFormElementData(formData) { 42011 // Take care of other input elements 42012 if (this.element.tagName === "FORM") { 42013 for (var _iterator24 = this.element.querySelectorAll("input, textarea, select, button"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) { 42014 var _ref23; 42015 42016 if (_isArray24) { 42017 if (_i26 >= _iterator24.length) break; 42018 _ref23 = _iterator24[_i26++]; 42019 } else { 42020 _i26 = _iterator24.next(); 42021 if (_i26.done) break; 42022 _ref23 = _i26.value; 42023 } 42024 42025 var input = _ref23; 42026 42027 var inputName = input.getAttribute("name"); 42028 var inputType = input.getAttribute("type"); 42029 if (inputType) inputType = inputType.toLowerCase(); 42030 42031 // If the input doesn't have a name, we can't use it. 42032 if (typeof inputName === 'undefined' || inputName === null) continue; 42033 42034 if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { 42035 // Possibly multiple values 42036 for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) { 42037 var _ref24; 42038 42039 if (_isArray25) { 42040 if (_i27 >= _iterator25.length) break; 42041 _ref24 = _iterator25[_i27++]; 42042 } else { 42043 _i27 = _iterator25.next(); 42044 if (_i27.done) break; 42045 _ref24 = _i27.value; 42046 } 42047 42048 var option = _ref24; 42049 42050 if (option.selected) { 42051 formData.append(inputName, option.value); 42052 } 42053 } 42054 } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) { 42055 formData.append(inputName, input.value); 42056 } 42057 } 42058 } 42059 } 42060 42061 // Invoked when there is new progress information about given files. 42062 // If e is not provided, it is assumed that the upload is finished. 42063 42064 }, { 42065 key: "_updateFilesUploadProgress", 42066 value: function _updateFilesUploadProgress(files, xhr, e) { 42067 var progress = void 0; 42068 if (typeof e !== 'undefined') { 42069 progress = 100 * e.loaded / e.total; 42070 42071 if (files[0].upload.chunked) { 42072 var file = files[0]; 42073 // Since this is a chunked upload, we need to update the appropriate chunk progress. 42074 var chunk = this._getChunk(file, xhr); 42075 chunk.progress = progress; 42076 chunk.total = e.total; 42077 chunk.bytesSent = e.loaded; 42078 var fileProgress = 0, 42079 fileTotal = void 0, 42080 fileBytesSent = void 0; 42081 file.upload.progress = 0; 42082 file.upload.total = 0;
42083 file.upload.bytesSent = 0; 42084 for (var i = 0; i < file.upload.totalChunkCount; i++) { 42085 if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) { 42086 file.upload.progress += file.upload.chunks[i].progress; 42087 file.upload.total += file.upload.chunks[i].total; 42088 file.upload.bytesSent += file.upload.chunks[i].bytesSent; 42089 } 42090 } 42091 file.upload.progress = file.upload.progress / file.upload.totalChunkCount; 42092 } else { 42093 for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) { 42094 var _ref25; 42095 42096 if (_isArray26) { 42097 if (_i28 >= _iterator26.length) break; 42098 _ref25 = _iterator26[_i28++]; 42099 } else { 42100 _i28 = _iterator26.next(); 42101 if (_i28.done) break; 42102 _ref25 = _i28.value; 42103 } 42104 42105 var _file2 = _ref25; 42106 42107 _file2.upload.progress = progress; 42108 _file2.upload.total = e.total; 42109 _file2.upload.bytesSent = e.loaded; 42110 } 42111 } 42112 for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) { 42113 var _ref26; 42114 42115 if (_isArray27) { 42116 if (_i29 >= _iterator27.length) break; 42117 _ref26 = _iterator27[_i29++]; 42118 } else { 42119 _i29 = _iterator27.next(); 42120 if (_i29.done) break; 42121 _ref26 = _i29.value; 42122 } 42123 42124 var _file3 = _ref26; 42125 42126 this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent); 42127 } 42128 } else { 42129 // Called when the file finished uploading 42130 42131 var allFilesFinished = true; 42132 42133 progress = 100; 42134 42135 for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) { 42136 var _ref27; 42137 42138 if (_isArray28) { 42139 if (_i30 >= _iterator28.length) break; 42140 _ref27 = _iterator28[_i30++]; 42141 } else { 42142 _i30 = _iterator28.next(); 42143 if (_i30.done) break; 42144 _ref27 = _i30.value; 42145 } 42146 42147 var _file4 = _ref27; 42148 42149 if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) { 42150 allFilesFinished = false; 42151 } 42152 _file4.upload.progress = progress; 42153 _file4.upload.bytesSent = _file4.upload.total; 42154 } 42155 42156 // Nothing to do, all files already at 100% 42157 if (allFilesFinished) { 42158 return; 42159 } 42160 42161 for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) { 42162 var _ref28; 42163 42164 if (_isArray29) { 42165 if (_i31 >= _iterator29.length) break; 42166 _ref28 = _iterator29[_i31++]; 42167 } else { 42168 _i31 = _iterator29.next(); 42169 if (_i31.done) break; 42170 _ref28 = _i31.value; 42171 } 42172 42173 var _file5 = _ref28; 42174 42175 this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent); 42176 } 42177 } 42178 } 42179 }, { 42180 key: "_finishedUploading", 42181 value: function _finishedUploading(files, xhr, e) { 42182 var response = void 0; 42183 42184 if (files[0].status === Dropzone.CANCELED) { 42185 return; 42186 } 42187 42188 if (xhr.readyState !== 4) { 42189 return; 42190 } 42191 42192 if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') { 42193 response = xhr.responseText; 42194 42195 if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { 42196 try { 42197 response = JSON.parse(response); 42198 } catch (error) { 42199 e = error; 42200 response = "Invalid JSON response from server."; 42201 } 42202 } 42203 } 42204 42205 this._updateFilesUploadProgress(files); 42206 42207 if (!(200 <= xhr.status && xhr.status < 300)) { 42208 this._handleUploadError(files, xhr, response); 42209 } else { 42210 if (files[0].upload.chunked) { 42211 files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr)); 42212 } else { 42213 this._finished(files, response, e); 42214 } 42215 } 42216 } 42217 }, { 42218 key: "_handleUploadError", 42219 value: function _handleUploadError(files, xhr, response) { 42220 if (files[0].status === Dropzone.CANCELED) { 42221 return; 42222 } 42223 42224 if (files[0].upload.chunked && this.options.retryChunks) { 42225 var chunk = this._getChunk(files[0], xhr); 42226 if (chunk.retries++ < this.options.retryChunksLimit) { 42227 this._uploadData(files, [chunk.dataBlock]); 42228 return; 42229 } else { 42230 console.warn('Retried this chunk too often. Giving up.'); 42231 } 42232 } 42233 42234 for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) { 42235 var _ref29; 42236 42237 if (_isArray30) { 42238 if (_i32 >= _iterator30.length) break; 42239 _ref29 = _iterator30[_i32++]; 42240 } else { 42241 _i32 = _iterator30.next(); 42242 if (_i32.done) break; 42243 _ref29 = _i32.value; 42244 } 42245 42246 var file = _ref29; 42247 42248 this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr); 42249 } 42250 } 42251 }, { 42252 key: "submitRequest", 42253 value: function submitRequest(xhr, formData, files) { 42254 xhr.send(formData); 42255 } 42256
42257 // Called internally when processing is finished. 42258 // Individual callbacks have to be called in the appropriate sections. 42259 42260 }, { 42261 key: "_finished", 42262 value: function _finished(files, responseText, e) { 42263 for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) { 42264 var _ref30; 42265 42266 if (_isArray31) { 42267 if (_i33 >= _iterator31.length) break; 42268 _ref30 = _iterator31[_i33++]; 42269 } else { 42270 _i33 = _iterator31.next(); 42271 if (_i33.done) break; 42272 _ref30 = _i33.value; 42273 } 42274 42275 var file = _ref30; 42276 42277 file.status = Dropzone.SUCCESS; 42278 this.emit("success", file, responseText, e); 42279 this.emit("complete", file); 42280 } 42281 if (this.options.uploadMultiple) { 42282 this.emit("successmultiple", files, responseText, e); 42283 this.emit("completemultiple", files); 42284 } 42285 42286 if (this.options.autoProcessQueue) { 42287 return this.processQueue(); 42288 } 42289 } 42290 42291 // Called internally when processing is finished. 42292 // Individual callbacks have to be called in the appropriate sections. 42293 42294 }, { 42295 key: "_errorProcessing", 42296 value: function _errorProcessing(files, message, xhr) { 42297 for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) { 42298 var _ref31; 42299 42300 if (_isArray32) { 42301 if (_i34 >= _iterator32.length) break; 42302 _ref31 = _iterator32[_i34++]; 42303 } else { 42304 _i34 = _iterator32.next(); 42305 if (_i34.done) break; 42306 _ref31 = _i34.value; 42307 } 42308 42309 var file = _ref31; 42310 42311 file.status = Dropzone.ERROR; 42312 this.emit("error", file, message, xhr); 42313 this.emit("complete", file); 42314 } 42315 if (this.options.uploadMultiple) { 42316 this.emit("errormultiple", files, message, xhr); 42317 this.emit("completemultiple", files); 42318 } 42319 42320 if (this.options.autoProcessQueue) { 42321 return this.processQueue(); 42322 } 42323 } 42324 }], [{ 42325 key: "uuidv4", 42326 value: function uuidv4() { 42327 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 42328 var r = Math.random() * 16 | 0, 42329 v = c === 'x' ? r : r & 0x3 | 0x8; 42330 return v.toString(16); 42331 }); 42332 } 42333 }]); 42334 42335 return Dropzone; 42336}(Emitter); 42337 42338Dropzone.initClass(); 42339 42340Dropzone.version = "5.5.1"; 42341 42342// This is a map of options for your different dropzones. Add configurations 42343// to this object for your different dropzone elemens. 42344// 42345// Example: 42346// 42347// Dropzone.options.myDropzoneElementId = { maxFilesize: 1 }; 42348// 42349// To disable autoDiscover for a specific element, you can set `false` as an option: 42350// 42351// Dropzone.options.myDisabledElementId = false; 42352// 42353// And in html: 42354// 42355// <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form> 42356Dropzone.options = {}; 42357 42358// Returns the options for an element or undefined if none available. 42359Dropzone.optionsForElement = function (element) { 42360 // Get the `Dropzone.options.elementId` for this element if it exists 42361 if (element.getAttribute("id")) { 42362 return Dropzone.options[camelize(element.getAttribute("id"))]; 42363 } else { 42364 return undefined; 42365 } 42366}; 42367 42368// Holds a list of all dropzone instances 42369Dropzone.instances = []; 42370 42371// Returns the dropzone for given element if any 42372Dropzone.forElement = function (element) { 42373 if (typeof element === "string") { 42374 element = document.querySelector(element); 42375 } 42376 if ((element != null ? element.dropzone : undefined) == null) { 42377 throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); 42378 } 42379 return element.dropzone; 42380}; 42381 42382// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements. 42383Dropzone.autoDiscover = true; 42384 42385// Looks for all .dropzone elements and creates a dropzone for them 42386Dropzone.discover = function () { 42387 var dropzones = void 0; 42388 if (document.querySelectorAll) { 42389 dropzones = document.querySelectorAll(".dropzone"); 42390 } else { 42391 dropzones = []; 42392 // IE :( 42393 var checkElements = function checkElements(elements) { 42394 return function () { 42395 var result = []; 42396 for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) { 42397 var _ref32; 42398 42399 if (_isArray33) { 42400 if (_i35 >= _iterator33.length) break; 42401 _ref32 = _iterator33[_i35++]; 42402 } else { 42403 _i35 = _iterator33.next(); 42404 if (_i35.done) break; 42405 _ref32 = _i35.value; 42406 } 42407 42408 var el = _ref32; 42409 42410 if (/(^| )dropzone($| )/.test(el.className)) { 42411 result.push(dropzones.push(el)); 42412 } else { 42413 result.push(undefined); 42414 } 42415 } 42416 return result; 42417 }(); 42418 }; 42419 checkElements(document.getElementsByTagName("div")); 42420 checkElements(document.getElementsByTagName("form")); 42421 } 42422 42423 return function () { 42424 var result = []; 42425 for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) { 42426 var _ref33; 42427 42428 if (_isArray34) { 42429 if (_i36 >= _iterator34.length) break; 42430 _ref33 = _iterator34[_i36++]; 42431 } else { 42432 _i36 = _iterator34.next(); 42433 if (_i36.done) break; 42434 _ref33 = _i36.value; 42435 } 42436 42437 var dropzone = _ref33; 42438 42439 // Create a dropzone unless auto discover has been disabled for specific element 42440 if (Dropzone.optionsForElement(dropzone) !== false) { 42441 result.push(new Dropzone(dropzone)); 42442 } else { 42443 result.push(undefined); 42444 } 42445 } 42446 return result; 42447 }(); 42448}; 42449 42450// Since the whole Drag'n'Drop API is pretty new, some browsers implement it, 42451// but not correctly. 42452// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know. 42453// But what to do when browsers *theoretically* support an API, but crash 42454// when using it. 42455// 42456// This is a list of regular expressions tested against navigator.userAgent 42457// 42458// ** It should only be used on browser that *do* support the API, but 42459// incorrectly ** 42460// 42461Dropzone.blacklistedBrowsers = [ 42462// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API. 42463/opera.*(Macintosh|Windows Phone).*version\/12/i]; 42464 42465// Checks if the browser is supported 42466Dropzone.isBrowserSupported = function () { 42467 var capableBrowser = true; 42468 42469 if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { 42470 if (!("classList" in document.createElement("a"))) { 42471 capableBrowser = false;
42472 } else { 42473 // The browser supports the API, but may be blacklisted. 42474 for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) { 42475 var _ref34; 42476 42477 if (_isArray35) { 42478 if (_i37 >= _iterator35.length) break; 42479 _ref34 = _iterator35[_i37++]; 42480 } else { 42481 _i37 = _iterator35.next(); 42482 if (_i37.done) break; 42483 _ref34 = _i37.value; 42484 } 42485 42486 var regex = _ref34; 42487 42488 if (regex.test(navigator.userAgent)) { 42489 capableBrowser = false; 42490 continue; 42491 } 42492 } 42493 } 42494 } else { 42495 capableBrowser = false; 42496 } 42497 42498 return capableBrowser; 42499}; 42500 42501Dropzone.dataURItoBlob = function (dataURI) { 42502 // convert base64 to raw binary data held in a string 42503 // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this 42504 var byteString = atob(dataURI.split(',')[1]); 42505 42506 // separate out the mime component 42507 var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 42508 42509 // write the bytes of the string to an ArrayBuffer 42510 var ab = new ArrayBuffer(byteString.length); 42511 var ia = new Uint8Array(ab); 42512 for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) { 42513 ia[i] = byteString.charCodeAt(i); 42514 } 42515 42516 // write the ArrayBuffer to a blob 42517 return new Blob([ab], { type: mimeString }); 42518}; 42519 42520// Returns an array without the rejected item 42521var without = function without(list, rejectedItem) { 42522 return list.filter(function (item) { 42523 return item !== rejectedItem; 42524 }).map(function (item) { 42525 return item; 42526 }); 42527}; 42528 42529// abc-def_ghi -> abcDefGhi 42530var camelize = function camelize(str) { 42531 return str.replace(/[\-_](\w)/g, function (match) { 42532 return match.charAt(1).toUpperCase(); 42533 }); 42534}; 42535 42536// Creates an element from string 42537Dropzone.createElement = function (string) { 42538 var div = document.createElement("div"); 42539 div.innerHTML = string; 42540 return div.childNodes[0]; 42541}; 42542 42543// Tests if given element is inside (or simply is) the container 42544Dropzone.elementInside = function (element, container) { 42545 if (element === container) { 42546 return true; 42547 } // Coffeescript doesn't support do/while loops 42548 while (element = element.parentNode) { 42549 if (element === container) { 42550 return true; 42551 } 42552 } 42553 return false; 42554}; 42555 42556Dropzone.getElement = function (el, name) { 42557 var element = void 0; 42558 if (typeof el === "string") { 42559 element = document.querySelector(el); 42560 } else if (el.nodeType != null) { 42561 element = el; 42562 } 42563 if (element == null) { 42564 throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); 42565 } 42566 return element; 42567}; 42568 42569Dropzone.getElements = function (els, name) { 42570 var el = void 0, 42571 elements = void 0; 42572 if (els instanceof Array) { 42573 elements = []; 42574 try { 42575 for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) { 42576 if (_isArray36) { 42577 if (_i38 >= _iterator36.length) break; 42578 el = _iterator36[_i38++]; 42579 } else { 42580 _i38 = _iterator36.next(); 42581 if (_i38.done) break; 42582 el = _i38.value; 42583 } 42584 42585 elements.push(this.getElement(el, name)); 42586 } 42587 } catch (e) { 42588 elements = null; 42589 } 42590 } else if (typeof els === "string") { 42591 elements = [];
42592 for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) { 42593 if (_isArray37) { 42594 if (_i39 >= _iterator37.length) break; 42595 el = _iterator37[_i39++]; 42596 } else { 42597 _i39 = _iterator37.next(); 42598 if (_i39.done) break; 42599 el = _i39.value; 42600 } 42601 42602 elements.push(el); 42603 } 42604 } else if (els.nodeType != null) { 42605 elements = [els]; 42606 } 42607 42608 if (elements == null || !elements.length) { 42609 throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); 42610 } 42611 42612 return elements; 42613}; 42614 42615// Asks the user the question and calls accepted or rejected accordingly 42616// 42617// The default implementation just uses `window.confirm` and then calls the 42618// appropriate callback. 42619Dropzone.confirm = function (question, accepted, rejected) { 42620 if (window.confirm(question)) { 42621 return accepted(); 42622 } else if (rejected != null) { 42623 return rejected(); 42624 } 42625}; 42626 42627// Validates the mime type like this: 42628// 42629// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept 42630Dropzone.isValidFile = function (file, acceptedFiles) { 42631 if (!acceptedFiles) { 42632 return true; 42633 } // If there are no accepted mime types, it's OK 42634 acceptedFiles = acceptedFiles.split(","); 42635 42636 var mimeType = file.type; 42637 var baseMimeType = mimeType.replace(/\/.*$/, ""); 42638 42639 for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) { 42640 var _ref35; 42641 42642 if (_isArray38) { 42643 if (_i40 >= _iterator38.length) break; 42644 _ref35 = _iterator38[_i40++]; 42645 } else { 42646 _i40 = _iterator38.next(); 42647 if (_i40.done) break; 42648 _ref35 = _i40.value; 42649 } 42650 42651 var validType = _ref35; 42652 42653 validType = validType.trim(); 42654 if (validType.charAt(0) === ".") { 42655 if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { 42656 return true; 42657 } 42658 } else if (/\/\*$/.test(validType)) { 42659 // This is something like a image/* mime type 42660 if (baseMimeType === validType.replace(/\/.*$/, "")) { 42661 return true; 42662 } 42663 } else { 42664 if (mimeType === validType) { 42665 return true; 42666 } 42667 } 42668 } 42669 42670 return false; 42671}; 42672 42673// Augment jQuery 42674if (typeof jQuery !== 'undefined' && jQuery !== null) { 42675 jQuery.fn.dropzone = function (options) { 42676 return this.each(function () { 42677 return new Dropzone(this, options); 42678 }); 42679 }; 42680} 42681 42682if (typeof module !== 'undefined' && module !== null) { 42683 module.exports = Dropzone; 42684} else { 42685 window.Dropzone = Dropzone; 42686} 42687 42688// Dropzone file status codes 42689Dropzone.ADDED = "added"; 42690 42691Dropzone.QUEUED = "queued"; 42692// For backwards compatibility. Now, if a file is accepted, it's either queued 42693// or uploading. 42694Dropzone.ACCEPTED = Dropzone.QUEUED; 42695 42696Dropzone.UPLOADING = "uploading"; 42697Dropzone.PROCESSING = Dropzone.UPLOADING; // alias 42698 42699Dropzone.CANCELED = "canceled"; 42700Dropzone.ERROR = "error"; 42701Dropzone.SUCCESS = "success"; 42702 42703/* 42704 42705 Bugfix for iOS 6 and 7 42706 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios 42707 based on the work of https://github.com/stomita/ios-imagefile-megapixel 42708 42709 */ 42710 42711// Detecting vertical squash in loaded image. 42712// Fixes a bug which squash image vertically while drawing into canvas for some images. 42713// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel 42714var detectVerticalSquash = function detectVerticalSquash(img) { 42715 var iw = img.naturalWidth; 42716 var ih = img.naturalHeight; 42717 var canvas = document.createElement("canvas"); 42718 canvas.width = 1; 42719 canvas.height = ih; 42720 var ctx = canvas.getContext("2d"); 42721 ctx.drawImage(img, 0, 0); 42722 42723 var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih), 42724 data = _ctx$getImageData.data; 42725 42726 // search image edge pixel position in case it is squashed vertically. 42727 42728 42729 var sy = 0; 42730 var ey = ih; 42731 var py = ih; 42732 while (py > sy) { 42733 var alpha = data[(py - 1) * 4 + 3]; 42734 42735 if (alpha === 0) { 42736 ey = py; 42737 } else { 42738 sy = py; 42739 } 42740 42741 py = ey + sy >> 1; 42742 } 42743 var ratio = py / ih; 42744 42745 if (ratio === 0) { 42746 return 1; 42747 } else { 42748 return ratio; 42749 } 42750}; 42751 42752// A replacement for context.drawImage 42753// (args are for source and destination). 42754var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { 42755 var vertSquashRatio = detectVerticalSquash(img); 42756 return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); 42757}; 42758 42759// Based on MinifyJpeg 42760// Source: http://www.perry.cz/files/ExifRestorer.js 42761// http://elicon.blog57.fc2.com/blog-entry-206.html 42762 42763var ExifRestore = function () { 42764 function ExifRestore() { 42765 _classCallCheck(this, ExifRestore); 42766 } 42767 42768 _createClass(ExifRestore, null, [{ 42769 key: "initClass", 42770 value: function initClass() { 42771 this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
42771+/='; 42772 } 42773 }, { 42774 key: "encode64", 42775 value: function encode64(input) { 42776 var output = ''; 42777 var chr1 = undefined; 42778 var chr2 = undefined; 42779 var chr3 = ''; 42780 var enc1 = undefined; 42781 var enc2 = undefined; 42782 var enc3 = undefined; 42783 var enc4 = ''; 42784 var i = 0; 42785 while (true) { 42786 chr1 = input[i++]; 42787 chr2 = input[i++]; 42788 chr3 = input[i++]; 42789 enc1 = chr1 >> 2; 42790 enc2 = (chr1 & 3) << 4 | chr2 >> 4; 42791 enc3 = (chr2 & 15) << 2 | chr3 >> 6; 42792 enc4 = chr3 & 63; 42793 if (isNaN(chr2)) { 42794 enc3 = enc4 = 64; 42795 } else if (isNaN(chr3)) { 42796 enc4 = 64; 42797 } 42798 output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4); 42799 chr1 = chr2 = chr3 = ''; 42800 enc1 = enc2 = enc3 = enc4 = ''; 42801 if (!(i < input.length)) { 42802 break; 42803 } 42804 } 42805 return output; 42806 } 42807 }, { 42808 key: "restore", 42809 value: function restore(origFileBase64, resizedFileBase64) { 42810 if (!origFileBase64.match('data:image/jpeg;base64,')) { 42811 return resizedFileBase64; 42812 } 42813 var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', '')); 42814 var segments = this.slice2Segments(rawImage); 42815 var image = this.exifManipulation(resizedFileBase64, segments); 42816 return "data:image/jpeg;base64," + this.encode64(image); 42817 } 42818 }, { 42819 key: "exifManipulation", 42820 value: function exifManipulation(resizedFileBase64, segments) { 42821 var exifArray = this.getExifArray(segments); 42822 var newImageArray = this.insertExif(resizedFileBase64, exifArray); 42823 var aBuffer = new Uint8Array(newImageArray); 42824 return aBuffer; 42825 } 42826 }, { 42827 key: "getExifArray", 42828 value: function getExifArray(segments) { 42829 var seg = undefined; 42830 var x = 0; 42831 while (x < segments.length) { 42832 seg = segments[x]; 42833 if (seg[0] === 255 & seg[1] === 225) { 42834 return seg; 42835 } 42836 x++; 42837 } 42838 return []; 42839 } 42840 }, { 42841 key: "insertExif", 42842 value: function insertExif(resizedFileBase64, exifArray) { 42843 var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', ''); 42844 var buf = this.decode64(imageData); 42845 var separatePoint = buf.indexOf(255, 3); 42846 var mae = buf.slice(0, separatePoint); 42847 var ato = buf.slice(separatePoint); 42848 var array = mae; 42849 array = array.concat(exifArray); 42850 array = array.concat(ato); 42851 return array; 42852 } 42853 }, { 42854 key: "slice2Segments", 42855 value: function slice2Segments(rawImageArray) { 42856 var head = 0; 42857 var segments = []; 42858 while (true) { 42859 var length; 42860 if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) { 42861 break; 42862 } 42863 if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) { 42864 head += 2; 42865 } else { 42866 length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3]; 42867 var endPoint = head + length + 2; 42868 var seg = rawImageArray.slice(head, endPoint); 42869 segments.push(seg); 42870 head = endPoint; 42871 } 42872 if (head > rawImageArray.length) { 42873 break; 42874 } 42875 } 42876 return segments; 42877 } 42878 }, { 42879 key: "decode64", 42880 value: function decode64(input) { 42881 var output = ''; 42882 var chr1 = undefined; 42883 var chr2 = undefined; 42884 var chr3 = ''; 42885 var enc1 = undefined; 42886 var enc2 = undefined; 42887 var enc3 = undefined; 42888 var enc4 = ''; 42889 var i = 0; 42890 var buf = []; 42891 // remove all characters that are not A-Z, a-z, 0-9, +, /, or = 42892 var base64test = /[^A-Za-z0-9\+\/\=]/g; 42893 if (base64test.exec(input)) { 42894 console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.'); 42895 } 42896 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 42897 while (true) { 42898 enc1 = this.KEY_STR.indexOf(input.charAt(i++)); 42899 enc2 = this.KEY_STR.indexOf(input.charAt(i++)); 42900 enc3 = this.KEY_STR.indexOf(input.charAt(i++)); 42901 enc4 = this.KEY_STR.indexOf(input.charAt(i++)); 42902 chr1 = enc1 << 2 | enc2 >> 4; 42903 chr2 = (enc2 & 15) << 4 | enc3 >> 2; 42904 chr3 = (enc3 & 3) << 6 | enc4; 42905 buf.push(chr1); 42906 if (enc3 !== 64) { 42907 buf.push(chr2); 42908 } 42909 if (enc4 !== 64) { 42910 buf.push(chr3); 42911 } 42912 chr1 = chr2 = chr3 = ''; 42913 enc1 = enc2 = enc3 = enc4 = ''; 42914 if (!(i < input.length)) { 42915 break; 42916 } 42917 } 42918 return buf; 42919 } 42920 }]); 42921 42922 return ExifRestore; 42923}(); 42924 42925ExifRestore.initClass(); 42926 42927/* 42928 * contentloaded.js 42929 * 42930 * Author: Diego Perini (diego.perini at gmail.com) 42931 * Summary: cross-browser wrapper for DOMContentLoaded 42932 * Updated: 20101020 42933 * License: MIT 42934 * Version: 1.2 42935 * 42936 * URL: 42937 * http://javascript.nwbox.com/ContentLoaded/ 42938 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE 42939 */ 42940 42941// @win window reference 42942// @fn function reference 42943var contentLoaded = function contentLoaded(win, fn) { 42944 var done = false;
42945 var top = true; 42946 var doc = win.document; 42947 var root = doc.documentElement; 42948 var add = doc.addEventListener ? "addEventListener" : "attachEvent"; 42949 var rem = doc.addEventListener ? "removeEventListener" : "detachEvent"; 42950 var pre = doc.addEventListener ? "" : "on"; 42951 var init = function init(e) { 42952 if (e.type === "readystatechange" && doc.readyState !== "complete") { 42953 return; 42954 } 42955 (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); 42956 if (!done && (done = true)) { 42957 return fn.call(win, e.type || e); 42958 } 42959 }; 42960 42961 var poll = function poll() { 42962 try { 42963 root.doScroll("left"); 42964 } catch (e) { 42965 setTimeout(poll, 50); 42966 return; 42967 } 42968 return init("poll"); 42969 }; 42970 42971 if (doc.readyState !== "complete") { 42972 if (doc.createEventObject && root.doScroll) { 42973 try { 42974 top = !win.frameElement; 42975 } catch (error) {} 42976 if (top) { 42977 poll(); 42978 } 42979 } 42980 doc[add](pre + "DOMContentLoaded", init, false); 42981 doc[add](pre + "readystatechange", init, false); 42982 return win[add](pre + "load", init, false); 42983 } 42984}; 42985 42986// As a single function to be able to write tests. 42987Dropzone._autoDiscoverFunction = function () { 42988 if (Dropzone.autoDiscover) { 42989 return Dropzone.discover(); 42990 } 42991}; 42992contentLoaded(window, Dropzone._autoDiscoverFunction); 42993 42994function __guard__(value, transform) { 42995 return typeof value !== 'undefined' && value !== null ? transform(value) : undefined; 42996} 42997function __guardMethod__(obj, methodName, transform) { 42998 if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') { 42999 return transform(obj, methodName); 43000 } else { 43001 return undefined; 43002 } 43003} 43004 43005/** 43006 * Super simple wysiwyg editor v0.8.12 43007 * https://summernote.org 43008 * 43009 * Copyright 2013- Alan Hong. and other contributors 43010 * summernote may be freely distributed under the MIT license. 43011 * 43012 * Date: 2019-05-16T08:16Z 43013 */ 43014(function (global, factory) { 43015 typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) : 43016 typeof define === 'function' && define.amd ? define(['jquery'], factory) : 43017 (global = global || self, factory(global.jQuery)); 43018}(this, function ($$1) { 'use strict'; 43019 43020 $$1 = $$1 && $$1.hasOwnProperty('default') ? $$1['default'] : $$1; 43021 43022 var Renderer = /** @class */ (function () {
43023 function Renderer(markup, children, options, callback) { 43024 this.markup = markup; 43025 this.children = children; 43026 this.options = options; 43027 this.callback = callback; 43028 } 43029 Renderer.prototype.render = function ($parent) { 43030 var $node = $$1(this.markup); 43031 if (this.options && this.options.contents) { 43032 $node.html(this.options.contents); 43033 } 43034 if (this.options && this.options.className) { 43035 $node.addClass(this.options.className); 43036 } 43037 if (this.options && this.options.data) { 43038 $$1.each(this.options.data, function (k, v) { 43039 $node.attr('data-' + k, v); 43040 }); 43041 } 43042 if (this.options && this.options.click) { 43043 $node.on('click', this.options.click); 43044 } 43045 if (this.children) { 43046 var $container_1 = $node.find('.note-children-container'); 43047 this.children.forEach(function (child) { 43048 child.render($container_1.length ? $container_1 : $node); 43049 }); 43050 } 43051 if (this.callback) { 43052 this.callback($node, this.options); 43053 } 43054 if (this.options && this.options.callback) { 43055 this.options.callback($node); 43056 } 43057 if ($parent) { 43058 $parent.append($node); 43059 } 43060 return $node; 43061 }; 43062 return Renderer; 43063 }()); 43064 var renderer = { 43065 create: function (markup, callback) { 43066 return function () { 43067 var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0]; 43068 var children = Array.isArray(arguments[0]) ? arguments[0] : []; 43069 if (options && options.children) { 43070 children = options.children; 43071 } 43072 return new Renderer(markup, children, options, callback); 43073 }; 43074 } 43075 }; 43076 43077 var editor = renderer.create('<div class="note-editor note-frame panel panel-default"/>'); 43078 var toolbar = renderer.create('<div class="note-toolbar panel-heading" role="toolbar"></div></div>'); 43079 var editingArea = renderer.create('<div class="note-editing-area"/>'); 43080 var codable = renderer.create('<textarea class="note-codable" role="textbox" aria-multiline="true"/>'); 43081 var editable = renderer.create('<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>'); 43082 var statusbar = renderer.create([ 43083 '<output class="note-status-output" aria-live="polite"/>', 43084 '<div class="note-statusbar d-flex justify-content-center" role="status">', 43085 ' <div class="note-resizebar" role="seperator" aria-orientation="horizontal" aria-label="Resize">', 43086 ' <div class="note-icon-bar"/>', 43087 ' <div class="note-icon-bar"/>', 43088 ' <div class="note-icon-bar"/>', 43089 ' </div>', 43090 '</div>', 43091 ].join('')); 43092 var airEditor = renderer.create('<div class="note-editor"/>'); 43093 var airEditable = renderer.create([ 43094 '<div class="note-editable" contentEditable="true" role="textbox" aria-multiline="true"/>', 43095 '<output class="note-status-output" aria-live="polite"/>', 43096 ].join('')); 43097 var buttonGroup = renderer.create('<div class="note-btn-group btn-group">'); 43098 var dropdown = renderer.create('<ul class="dropdown-menu" role="list">', function ($node, options) { 43099 var markup = Array.isArray(options.items) ? options.items.map(function (item) { 43100 var value = (typeof item === 'string') ? item : (item.value || ''); 43101 var content = options.template ? options.template(item) : item; 43102 var option = (typeof item === 'object') ? item.option : undefined; 43103 var dataValue = 'data-value="' + value + '"'; 43104 var dataOption = (option !== undefined) ? ' data-option="' + option + '"' : ''; 43105 return '<li role="listitem" aria-label="' + value + '"><a href="#" ' + (dataValue + dataOption) + '>' + content + '</a></li>'; 43106 }).join('') : options.items; 43107 $node.html(markup).attr({ 'aria-label': options.title }); 43108 }); 43109 var dropdownButtonContents = function (contents, options) { 43110 return contents + ' ' + icon(options.icons.caret, 'span'); 43111 }; 43112 var dropdownCheck = renderer.create('<ul class="dropdown-menu note-check" role="list">', function ($node, options) { 43113 var markup = Array.isArray(options.items) ? options.items.map(function (item) { 43114 var value = (typeof item === 'string') ? item : (item.value || ''); 43115 var content = options.template ? options.template(item) : item; 43116 return '<li role="listitem" aria-label="' + item + '"><a href="#" data-value="' + value + '">' + icon(options.checkClassName) + ' ' + content + '</a></li>'; 43117 }).join('') : options.items; 43118 $node.html(markup).attr({ 'aria-label': options.title }); 43119 }); 43120 var palette = renderer.create('<div class="note-color-palette"/>', function ($node, options) { 43121 var contents = []; 43122 for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) { 43123 var eventName = options.eventName; 43124 var colors = options.colors[row]; 43125 var colorsName = options.colorsName[row]; 43126 var buttons = []; 43127 for (var col = 0, colSize = colors.length; col < colSize; col++) { 43128 var color = colors[col]; 43129 var colorName = colorsName[col]; 43130 buttons.push([ 43131 '<button type="button" class="note-color-btn"', 43132 'style="background-color:', color, '" ', 43133 'data-event="', eventName, '" ', 43134 'data-value="', color, '" ', 43135 'title="', colorName, '" ', 43136 'aria-label="', colorName, '" ', 43137 'data-toggle="button" tabindex="-1"></button>', 43138 ].join('')); 43139 } 43140 contents.push('<div class="note-color-row">' + buttons.join('') + '</div>'); 43141 } 43142 $node.html(contents.join('')); 43143 if (options.tooltip) { 43144 $node.find('.note-color-btn').tooltip({ 43145 container: options.container, 43146 trigger: 'hover', 43147 placement: 'bottom' 43148 }); 43149 } 43150 }); 43151 var dialog = renderer.create('<div class="modal" aria-hidden="false" tabindex="-1" role="dialog"/>', function ($node, options) { 43152 if (options.fade) { 43153 $node.addClass('fade'); 43154 } 43155 $node.attr({ 43156 'aria-label': options.title 43157 }); 43158 $node.html([ 43159 '<div class="modal-dialog">', 43160 ' <div class="modal-content">', 43161 (options.title 43162 ? ' <div class="modal-header">' + 43163 ' <h4 class="modal-title">' + options.title + '</h4>' + 43164 ' <button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true"></button>' + 43165 ' </div>' : ''), 43166 ' <div class="modal-body">' + options.body + '</div>', 43167 (options.footer 43168 ? ' <div class="modal-footer">' + options.footer + '</div>' : ''), 43169 ' </div>', 43170 '</div>', 43171 ].join('')); 43172 }); 43173 var popover = renderer.create([ 43174 '<div class="note-popover popover in">', 43175 ' <div class="arrow"/>', 43176 ' <div class="popover-content note-children-container"/>', 43177 '</div>', 43178 ].join(''), function ($node, options) { 43179 var direction = typeof options.direction !== 'undefined' ? options.direction : 'bottom'; 43180 $node.addClass(direction); 43181 if (options.hideArrow) { 43182 $node.find('.arrow').hide(); 43183 } 43184 }); 43185 var checkbox = renderer.create('<div class="checkbox"></div>', function ($node, options) { 43186 $node.html([ 43187 '<label' + (options.id ? ' for="' + options.id + '"' : '') + '>', 43188 ' <input role="checkbox" type="checkbox"' + (options.id ? ' id="' + options.id + '"' : ''), 43189 (options.checked ? ' checked' : ''), 43190 ' aria-checked="' + (options.checked ? 'true' : 'false') + '"/>', 43191 (options.text ? options.text : ''), 43192 '</label>', 43193 ].join('')); 43194 }); 43195 var icon = function (iconClassName, tagName) { 43196 tagName = tagName || 'i'; 43197 return '<' + tagName + ' class="' + iconClassName + '"/>'; 43198 }; 43199 var ui = { 43200 editor: editor, 43201 toolbar: toolbar, 43202 editingArea: editingArea, 43203 codable: codable, 43204 editable: editable, 43205 statusbar: statusbar, 43206 airEditor: airEditor, 43207 airEditable: airEditable, 43208 buttonGroup: buttonGroup, 43209 dropdown: dropdown, 43210 dropdownButtonContents: dropdownButtonContents, 43211 dropdownCheck: dropdownCheck, 43212 palette: palette, 43213 dialog: dialog, 43214 popover: popover, 43215 checkbox: checkbox, 43216 icon: icon, 43217 options: {}, 43218 button: function ($node, options) { 43219 return renderer.create('<button type="button" class="note-btn btn btn-default btn-sm" role="button" tabindex="-1">', function ($node, options) { 43220 if (options && options.tooltip) { 43221 $node.attr({ 43222 title: options.tooltip, 43223 'aria-label': options.tooltip 43224 }).tooltip({ 43225 container: (options.container !== undefined) ? options.container : 'body', 43226 trigger: 'hover', 43227 placement: 'bottom' 43228 }).on('click', function (e) { 43229 $$1(e.currentTarget).tooltip('hide'); 43230 }); 43231 } 43232 })($node, options); 43233 }, 43234 toggleBtn: function ($btn, isEnable) { 43235 $btn.toggleClass('disabled', !isEnable); 43236 $btn.attr('disabled', !isEnable); 43237 }, 43238 toggleBtnActive: function ($btn, isActive) { 43239 $btn.toggleClass('active', isActive); 43240 }, 43241 onDialogShown: function ($dialog, handler) { 43242 $dialog.one('shown.bs.modal', handler); 43243 }, 43244 onDialogHidden: function ($dialog, handler) { 43245 $dialog.one('hidden.bs.modal', handler); 43246 }, 43247 showDialog: function ($dialog) { 43248 $dialog.modal('show'); 43249 }, 43250 hideDialog: function ($dialog) { 43251 $dialog.modal('hide'); 43252 }, 43253 createLayout: function ($note, options) { 43254 var $editor = (options.airMode ? ui.airEditor([ 43255 ui.editingArea([ 43256 ui.airEditable(), 43257 ]), 43258 ]) : ui.editor([ 43259 ui.toolbar(), 43260 ui.editingArea([ 43261 ui.codable(), 43262 ui.editable(), 43263 ]), 43264 ui.statusbar(), 43265 ])).render(); 43266 $editor.insertAfter($note); 43267 return { 43268 note: $note, 43269 editor: $editor, 43270 toolbar: $editor.find('.note-toolbar'), 43271 editingArea: $editor.find('.note-editing-area'), 43272 editable: $editor.find('.note-editable'), 43273 codable: $editor.find('.note-codable'), 43274 statusbar: $editor.find('.note-statusbar') 43275 }; 43276 }, 43277 removeLayout: function ($note, layoutInfo) { 43278 $note.html(layoutInfo.editable.html()); 43279 layoutInfo.editor.remove(); 43280 $note.show(); 43281 } 43282 }; 43283 43284 $$1.summernote = $$1.summernote || { 43285 lang: {} 43286 }; 43287 $$1.extend($$1.summernote.lang, { 43288 'en-US': { 43289 font: { 43290 bold: 'Bold', 43291 italic: 'Italic', 43292 underline: 'Underline', 43293 clear: 'Remove Font Style', 43294 height: 'Line Height', 43295 name: 'Font Family',
43296 strikethrough: 'Strikethrough', 43297 subscript: 'Subscript', 43298 superscript: 'Superscript', 43299 size: 'Font Size' 43300 }, 43301 image: { 43302 image: 'Picture', 43303 insert: 'Insert Image', 43304 resizeFull: 'Resize full', 43305 resizeHalf: 'Resize half', 43306 resizeQuarter: 'Resize quarter', 43307 resizeNone: 'Original size', 43308 floatLeft: 'Float Left', 43309 floatRight: 'Float Right', 43310 floatNone: 'Remove float', 43311 shapeRounded: 'Shape: Rounded', 43312 shapeCircle: 'Shape: Circle', 43313 shapeThumbnail: 'Shape: Thumbnail', 43314 shapeNone: 'Shape: None', 43315 dragImageHere: 'Drag image or text here', 43316 dropImage: 'Drop image or Text', 43317 selectFromFiles: 'Select from files', 43318 maximumFileSize: 'Maximum file size', 43319 maximumFileSizeError: 'Maximum file size exceeded.', 43320 url: 'Image URL', 43321 remove: 'Remove Image', 43322 original: 'Original' 43323 }, 43324 video: { 43325 video: 'Video', 43326 videoLink: 'Video Link', 43327 insert: 'Insert Video', 43328 url: 'Video URL', 43329 providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)' 43330 }, 43331 link: { 43332 link: 'Link', 43333 insert: 'Insert Link', 43334 unlink: 'Unlink', 43335 edit: 'Edit', 43336 textToDisplay: 'Text to display', 43337 url: 'To what URL should this link go?', 43338 openInNewWindow: 'Open in new window' 43339 }, 43340 table: { 43341 table: 'Table', 43342 addRowAbove: 'Add row above', 43343 addRowBelow: 'Add row below', 43344 addColLeft: 'Add column left', 43345 addColRight: 'Add column right', 43346 delRow: 'Delete row', 43347 delCol: 'Delete column', 43348 delTable: 'Delete table' 43349 }, 43350 hr: { 43351 insert: 'Insert Horizontal Rule' 43352 }, 43353 style: { 43354 style: 'Style', 43355 p: 'Normal', 43356 blockquote: 'Quote', 43357 pre: 'Code', 43358 h1: 'Header 1', 43359 h2: 'Header 2', 43360 h3: 'Header 3', 43361 h4: 'Header 4', 43362 h5: 'Header 5', 43363 h6: 'Header 6' 43364 }, 43365 lists: { 43366 unordered: 'Unordered list', 43367 ordered: 'Ordered list' 43368 }, 43369 options: { 43370 help: 'Help', 43371 fullscreen: 'Full Screen', 43372 codeview: 'Code View' 43373 }, 43374 paragraph: { 43375 paragraph: 'Paragraph', 43376 outdent: 'Outdent', 43377 indent: 'Indent', 43378 left: 'Align left', 43379 center: 'Align center', 43380 right: 'Align right', 43381 justify: 'Justify full' 43382 }, 43383 color: { 43384 recent: 'Recent Color', 43385 more: 'More Color', 43386 background: 'Background Color', 43387 foreground: 'Foreground Color', 43388 transparent: 'Transparent', 43389 setTransparent: 'Set transparent', 43390 reset: 'Reset', 43391 resetToDefault: 'Reset to default', 43392 cpSelect: 'Select' 43393 }, 43394 shortcut: { 43395 shortcuts: 'Keyboard shortcuts', 43396 close: 'Close', 43397 textFormatting: 'Text formatting', 43398 action: 'Action', 43399 paragraphFormatting: 'Paragraph formatting', 43400 documentStyle: 'Document Style', 43401 extraKeys: 'Extra keys' 43402 }, 43403 help: { 43404 'insertParagraph': 'Insert Paragraph', 43405 'undo': 'Undoes the last command', 43406 'redo': 'Redoes the last command', 43407 'tab': 'Tab', 43408 'untab': 'Untab', 43409 'bold': 'Set a bold style', 43410 'italic': 'Set a italic style', 43411 'underline': 'Set a underline style', 43412 'strikethrough': 'Set a strikethrough style', 43413 'removeFormat': 'Clean a style', 43414 'justifyLeft': 'Set left align', 43415 'justifyCenter': 'Set center align', 43416 'justifyRight': 'Set right align', 43417 'justifyFull': 'Set full align', 43418 'insertUnorderedList': 'Toggle unordered list', 43419 'insertOrderedList': 'Toggle ordered list', 43420 'outdent': 'Outdent on current paragraph', 43421 'indent': 'Indent on current paragraph', 43422 'formatPara': 'Change current block\'s format as a paragraph(P tag)', 43423 'formatH1': 'Change current block\'s format as H1', 43424 'formatH2': 'Change current block\'s format as H2', 43425 'formatH3': 'Change current block\'s format as H3', 43426 'formatH4': 'Change current block\'s format as H4', 43427 'formatH5': 'Change current block\'s format as H5', 43428 'formatH6': 'Change current block\'s format as H6', 43429 'insertHorizontalRule': 'Insert horizontal rule', 43430 'linkDialog.show': 'Show Link Dialog' 43431 }, 43432 history: { 43433 undo: 'Undo', 43434 redo: 'Redo' 43435 }, 43436 specialChar: { 43437 specialChar: 'SPECIAL CHARACTERS', 43438 select: 'Select Special characters' 43439 } 43440 } 43441 }); 43442 43443 var isSupportAmd = typeof define === 'function' && define.amd; // eslint-disable-line 43444 /** 43445 * returns whether font is installed or not. 43446 * 43447 * @param {String} fontName 43448 * @return {Boolean} 43449 */ 43450 function isFontInstalled(fontName) { 43451 var testFontName = fontName === 'Comic Sans MS' ? 'Courier New' : 'Comic Sans MS'; 43452 var testText = 'mmmmmmmmmmwwwww'; 43453 var testSize = '200px'; 43454 var canvas = document.createElement('canvas'); 43455 var context = canvas.getContext('2d'); 43456 context.font = testSize + " '" + testFontName + "'"; 43457 var originalWidth = context.measureText(testText).width; 43458 context.font = testSize + " '" + fontName + "', '" + testFontName + "'"; 43459 var width = context.measureText(testText).width; 43460 return originalWidth !== width; 43461 } 43462 var userAgent = navigator.userAgent; 43463 var isMSIE = /MSIE|Trident/i.test(userAgent); 43464 var browserVersion; 43465 if (isMSIE) { 43466 var matches = /MSIE (\d+[.]\d+)/.exec(userAgent); 43467 if (matches) { 43468 browserVersion = parseFloat(matches[1]); 43469 } 43470 matches = /Trident\/.*rv:([0-9]{1,}[.0-9]{0,})/.exec(userAgent); 43471 if (matches) { 43472 browserVersion = parseFloat(matches[1]); 43473 } 43474 } 43475 var isEdge = /Edge\/\d+/.test(userAgent); 43476 var hasCodeMirror = !!window.CodeMirror; 43477 var isSupportTouch = (('ontouchstart' in window) || 43478 (navigator.MaxTouchPoints > 0) || 43479 (navigator.msMaxTouchPoints > 0)); 43480 // [workaround] IE doesn't have input events for contentEditable 43481 // - see: https://goo.gl/4bfIvA 43482 var inputEventName = (isMSIE || isEdge) ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input'; 43483 /** 43484 * @class core.env 43485 * 43486 * Object which check platform and agent 43487 * 43488 * @singleton 43489 * @alternateClassName env 43490 */ 43491 var env = { 43492 isMac: navigator.appVersion.indexOf('Mac') > -1, 43493 isMSIE: isMSIE, 43494 isEdge: isEdge, 43495 isFF: !isEdge && /firefox/i.test(userAgent), 43496 isPhantom: /PhantomJS/i.test(userAgent), 43497 isWebkit: !isEdge && /webkit/i.test(userAgent), 43498 isChrome: !isEdge && /chrome/i.test(userAgent), 43499 isSafari: !isEdge && /safari/i.test(userAgent), 43500 browserVersion: browserVersion, 43501 jqueryVersion: parseFloat($$1.fn.jquery), 43502 isSupportAmd: isSupportAmd,
vendor: 37,811 bytes, lines 43503-44904
43503 isSupportTouch: isSupportTouch, 43504 hasCodeMirror: hasCodeMirror, 43505 isFontInstalled: isFontInstalled, 43506 isW3CRangeSupport: !!document.createRange, 43507 inputEventName: inputEventName 43508 }; 43509 43510 /** 43511 * @class core.func 43512 * 43513 * func utils (for high-order func's arg) 43514 * 43515 * @singleton 43516 * @alternateClassName func 43517 */ 43518 function eq(itemA) { 43519 return function (itemB) { 43520 return itemA === itemB; 43521 }; 43522 } 43523 function eq2(itemA, itemB) { 43524 return itemA === itemB; 43525 } 43526 function peq2(propName) { 43527 return function (itemA, itemB) { 43528 return itemA[propName] === itemB[propName]; 43529 }; 43530 } 43531 function ok() { 43532 return true; 43533 } 43534 function fail() { 43535 return false; 43536 } 43537 function not(f) { 43538 return function () { 43539 return !f.apply(f, arguments); 43540 }; 43541 } 43542 function and(fA, fB) { 43543 return function (item) { 43544 return fA(item) && fB(item); 43545 }; 43546 } 43547 function self(a) { 43548 return a; 43549 } 43550 function invoke(obj, method) { 43551 return function () { 43552 return obj[method].apply(obj, arguments); 43553 }; 43554 } 43555 var idCounter = 0; 43556 /** 43557 * generate a globally-unique id 43558 * 43559 * @param {String} [prefix] 43560 */ 43561 function uniqueId(prefix) { 43562 var id = ++idCounter + ''; 43563 return prefix ? prefix + id : id; 43564 } 43565 /** 43566 * returns bnd (bounds) from rect 43567 * 43568 * - IE Compatibility Issue: http://goo.gl/sRLOAo 43569 * - Scroll Issue: http://goo.gl/sNjUc 43570 * 43571 * @param {Rect} rect 43572 * @return {Object} bounds 43573 * @return {Number} bounds.top 43574 * @return {Number} bounds.left 43575 * @return {Number} bounds.width 43576 * @return {Number} bounds.height 43577 */ 43578 function rect2bnd(rect) { 43579 var $document = $(document); 43580 return { 43581 top: rect.top + $document.scrollTop(), 43582 left: rect.left + $document.scrollLeft(), 43583 width: rect.right - rect.left, 43584 height: rect.bottom - rect.top 43585 }; 43586 } 43587 /** 43588 * returns a copy of the object where the keys have become the values and the values the keys. 43589 * @param {Object} obj 43590 * @return {Object} 43591 */ 43592 function invertObject(obj) { 43593 var inverted = {}; 43594 for (var key in obj) { 43595 if (obj.hasOwnProperty(key)) { 43596 inverted[obj[key]] = key; 43597 } 43598 } 43599 return inverted; 43600 } 43601 /** 43602 * @param {String} namespace 43603 * @param {String} [prefix] 43604 * @return {String} 43605 */ 43606 function namespaceToCamel(namespace, prefix) { 43607 prefix = prefix || ''; 43608 return prefix + namespace.split('.').map(function (name) { 43609 return name.substring(0, 1).toUpperCase() + name.substring(1); 43610 }).join(''); 43611 } 43612 /** 43613 * Returns a function, that, as long as it continues to be invoked, will not 43614 * be triggered. The function will be called after it stops being called for 43615 * N milliseconds. If `immediate` is passed, trigger the function on the 43616 * leading edge, instead of the trailing. 43617 * @param {Function} func 43618 * @param {Number} wait 43619 * @param {Boolean} immediate 43620 * @return {Function} 43621 */ 43622 function debounce(func, wait, immediate) { 43623 var timeout; 43624 return function () { 43625 var context = this; 43626 var args = arguments; 43627 var later = function () { 43628 timeout = null; 43629 if (!immediate) { 43630 func.apply(context, args); 43631 } 43632 }; 43633 var callNow = immediate && !timeout; 43634 clearTimeout(timeout); 43635 timeout = setTimeout(later, wait); 43636 if (callNow) { 43637 func.apply(context, args); 43638 } 43639 }; 43640 } 43641 /** 43642 * 43643 * @param {String} url 43644 * @return {Boolean} 43645 */ 43646 function isValidUrl(url) { 43647 var expression = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/gi; 43648 return expression.test(url); 43649 } 43650 var func = { 43651 eq: eq, 43652 eq2: eq2, 43653 peq2: peq2, 43654 ok: ok, 43655 fail: fail, 43656 self: self, 43657 not: not, 43658 and: and, 43659 invoke: invoke, 43660 uniqueId: uniqueId, 43661 rect2bnd: rect2bnd, 43662 invertObject: invertObject, 43663 namespaceToCamel: namespaceToCamel, 43664 debounce: debounce, 43665 isValidUrl: isValidUrl 43666 }; 43667 43668 /** 43669 * returns the first item of an array. 43670 * 43671 * @param {Array} array 43672 */ 43673 function head(array) { 43674 return array[0]; 43675 } 43676 /** 43677 * returns the last item of an array. 43678 * 43679 * @param {Array} array 43680 */ 43681 function last(array) { 43682 return array[array.length - 1]; 43683 } 43684 /** 43685 * returns everything but the last entry of the array. 43686 * 43687 * @param {Array} array 43688 */ 43689 function initial(array) { 43690 return array.slice(0, array.length - 1); 43691 } 43692 /** 43693 * returns the rest of the items in an array. 43694 * 43695 * @param {Array} array 43696 */ 43697 function tail(array) { 43698 return array.slice(1); 43699 } 43700 /** 43701 * returns item of array 43702 */ 43703 function find(array, pred) { 43704 for (var idx = 0, len = array.length; idx < len; idx++) { 43705 var item = array[idx]; 43706 if (pred(item)) { 43707 return item; 43708 } 43709 } 43710 } 43711 /** 43712 * returns true if all of the values in the array pass the predicate truth test. 43713 */ 43714 function all(array, pred) { 43715 for (var idx = 0, len = array.length; idx < len; idx++) { 43716 if (!pred(array[idx])) { 43717 return false; 43718 } 43719 } 43720 return true; 43721 } 43722 /** 43723 * returns true if the value is present in the list. 43724 */ 43725 function contains(array, item) { 43726 if (array && array.length && item) { 43727 return array.indexOf(item) !== -1; 43728 } 43729 return false; 43730 } 43731 /** 43732 * get sum from a list 43733 * 43734 * @param {Array} array - array 43735 * @param {Function} fn - iterator 43736 */ 43737 function sum(array, fn) { 43738 fn = fn || func.self; 43739 return array.reduce(function (memo, v) { 43740 return memo + fn(v); 43741 }, 0); 43742 } 43743 /** 43744 * returns a copy of the collection with array type. 43745 * @param {Collection} collection - collection eg) node.childNodes, ... 43746 */ 43747 function from(collection) { 43748 var result = []; 43749 var length = collection.length; 43750 var idx = -1; 43751 while (++idx < length) { 43752 result[idx] = collection[idx]; 43753 } 43754 return result; 43755 } 43756 /** 43757 * returns whether list is empty or not 43758 */ 43759 function isEmpty(array) { 43760 return !array || !array.length; 43761 } 43762 /** 43763 * cluster elements by predicate function. 43764 * 43765 * @param {Array} array - array 43766 * @param {Function} fn - predicate function for cluster rule 43767 * @param {Array[]} 43768 */ 43769 function clusterBy(array, fn) { 43770 if (!array.length) { 43771 return []; 43772 } 43773 var aTail = tail(array); 43774 return aTail.reduce(function (memo, v) { 43775 var aLast = last(memo); 43776 if (fn(last(aLast), v)) { 43777 aLast[aLast.length] = v; 43778 } 43779 else { 43780 memo[memo.length] = [v]; 43781 } 43782 return memo; 43783 }, [[head(array)]]); 43784 } 43785 /** 43786 * returns a copy of the array with all false values removed 43787 * 43788 * @param {Array} array - array 43789 * @param {Function} fn - predicate function for cluster rule 43790 */ 43791 function compact(array) { 43792 var aResult = []; 43793 for (var idx = 0, len = array.length; idx < len; idx++) { 43794 if (array[idx]) { 43795 aResult.push(array[idx]); 43796 } 43797 } 43798 return aResult; 43799 } 43800 /** 43801 * produces a duplicate-free version of the array 43802 * 43803 * @param {Array} array 43804 */ 43805 function unique(array) { 43806 var results = []; 43807 for (var idx = 0, len = array.length; idx < len; idx++) { 43808 if (!contains(results, array[idx])) { 43809 results.push(array[idx]); 43810 } 43811 } 43812 return results; 43813 } 43814 /** 43815 * returns next item. 43816 * @param {Array} array 43817 */ 43818 function next(array, item) { 43819 if (array && array.length && item) { 43820 var idx = array.indexOf(item); 43821 return idx === -1 ? null : array[idx + 1]; 43822 } 43823 return null; 43824 } 43825 /** 43826 * returns prev item. 43827 * @param {Array} array 43828 */ 43829 function prev(array, item) { 43830 if (array && array.length && item) { 43831 var idx = array.indexOf(item); 43832 return idx === -1 ? null : array[idx - 1]; 43833 } 43834 return null; 43835 } 43836 /** 43837 * @class core.list 43838 * 43839 * list utils 43840 * 43841 * @singleton 43842 * @alternateClassName list 43843 */ 43844 var lists = { 43845 head: head, 43846 last: last, 43847 initial: initial, 43848 tail: tail, 43849 prev: prev, 43850 next: next, 43851 find: find, 43852 contains: contains, 43853 all: all, 43854 sum: sum, 43855 from: from, 43856 isEmpty: isEmpty, 43857 clusterBy: clusterBy, 43858 compact: compact, 43859 unique: unique 43860 }; 43861 43862 var NBSP_CHAR = String.fromCharCode(160); 43863 var ZERO_WIDTH_NBSP_CHAR = '\ufeff'; 43864 /** 43865 * @method isEditable 43866 * 43867 * returns whether node is `note-editable` or not. 43868 * 43869 * @param {Node} node 43870 * @return {Boolean} 43871 */ 43872 function isEditable(node) { 43873 return node && $$1(node).hasClass('note-editable'); 43874 } 43875 /** 43876 * @method isControlSizing 43877 * 43878 * returns whether node is `note-control-sizing` or not. 43879 * 43880 * @param {Node} node 43881 * @return {Boolean} 43882 */ 43883 function isControlSizing(node) { 43884 return node && $$1(node).hasClass('note-control-sizing'); 43885 } 43886 /** 43887 * @method makePredByNodeName 43888 * 43889 * returns predicate which judge whether nodeName is same 43890 * 43891 * @param {String} nodeName 43892 * @return {Function} 43893 */ 43894 function makePredByNodeName(nodeName) { 43895 nodeName = nodeName.toUpperCase(); 43896 return function (node) { 43897 return node && node.nodeName.toUpperCase() === nodeName; 43898 }; 43899 } 43900 /** 43901 * @method isText 43902 * 43903 * 43904 * 43905 * @param {Node} node 43906 * @return {Boolean} true if node's type is text(3) 43907 */ 43908 function isText(node) { 43909 return node && node.nodeType === 3; 43910 } 43911 /** 43912 * @method isElement 43913 * 43914 * 43915 * 43916 * @param {Node} node 43917 * @return {Boolean} true if node's type is element(1) 43918 */ 43919 function isElement(node) { 43920 return node && node.nodeType === 1; 43921 } 43922 /** 43923 * ex) br, col, embed, hr, img, input, ... 43924 * @see http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements 43925 */ 43926 function isVoid(node) { 43927 return node && /^BR|^IMG|^HR|^IFRAME|^BUTTON|^INPUT|^AUDIO|^VIDEO|^EMBED/.test(node.nodeName.toUpperCase()); 43928 } 43929 function isPara(node) { 43930 if (isEditable(node)) { 43931 return false; 43932 } 43933 // Chrome(v31.0), FF(v25.0.1) use DIV for paragraph 43934 return node && /^DIV|^P|^LI|^H[1-7]/.test(node.nodeName.toUpperCase()); 43935 } 43936 function isHeading(node) { 43937 return node && /^H[1-7]/.test(node.nodeName.toUpperCase()); 43938 } 43939 var isPre = makePredByNodeName('PRE'); 43940 var isLi = makePredByNodeName('LI'); 43941 function isPurePara(node) { 43942 return isPara(node) && !isLi(node); 43943 } 43944 var isTable = makePredByNodeName('TABLE'); 43945 var isData = makePredByNodeName('DATA'); 43946 function isInline(node) { 43947 return !isBodyContainer(node) && 43948 !isList(node) && 43949 !isHr(node) && 43950 !isPara(node) && 43951 !isTable(node) && 43952 !isBlockquote(node) && 43953 !isData(node); 43954 } 43955 function isList(node) { 43956 return node && /^UL|^OL/.test(node.nodeName.toUpperCase()); 43957 } 43958 var isHr = makePredByNodeName('HR'); 43959 function isCell(node) { 43960 return node && /^TD|^TH/.test(node.nodeName.toUpperCase()); 43961 } 43962 var isBlockquote = makePredByNodeName('BLOCKQUOTE'); 43963 function isBodyContainer(node) { 43964 return isCell(node) || isBlockquote(node) || isEditable(node); 43965 } 43966 var isAnchor = makePredByNodeName('A'); 43967 function isParaInline(node) { 43968 return isInline(node) && !!ancestor(node, isPara); 43969 } 43970 function isBodyInline(node) { 43971 return isInline(node) && !ancestor(node, isPara); 43972 } 43973 var isBody = makePredByNodeName('BODY'); 43974 /** 43975 * returns whether nodeB is closest sibling of nodeA 43976 * 43977 * @param {Node} nodeA 43978 * @param {Node} nodeB 43979 * @return {Boolean} 43980 */ 43981 function isClosestSibling(nodeA, nodeB) { 43982 return nodeA.nextSibling === nodeB || 43983 nodeA.previousSibling === nodeB; 43984 } 43985 /** 43986 * returns array of closest siblings with node 43987 * 43988 * @param {Node} node 43989 * @param {function} [pred] - predicate function 43990 * @return {Node[]} 43991 */ 43992 function withClosestSiblings(node, pred) { 43993 pred = pred || func.ok; 43994 var siblings = []; 43995 if (node.previousSibling && pred(node.previousSibling)) { 43996 siblings.push(node.previousSibling); 43997 } 43998 siblings.push(node); 43999 if (node.nextSibling && pred(node.nextSibling)) { 44000 siblings.push(node.nextSibling); 44001 } 44002 return siblings; 44003 } 44004 /** 44005 * blank HTML for cursor position 44006 * - [workaround] old IE only works with 44007 * - [workaround] IE11 and other browser works with bogus br 44008 */ 44009 var blankHTML = env.isMSIE && env.browserVersion < 11 ? ' ' : '<br>'; 44010 /** 44011 * @method nodeLength 44012 * 44013 * returns #text's text size or element's childNodes size 44014 * 44015 * @param {Node} node 44016 */ 44017 function nodeLength(node) { 44018 if (isText(node)) { 44019 return node.nodeValue.length; 44020 } 44021 if (node) { 44022 return node.childNodes.length; 44023 } 44024 return 0; 44025 } 44026 /** 44027 * returns whether node is empty or not. 44028 * 44029 * @param {Node} node 44030 * @return {Boolean} 44031 */ 44032 function isEmpty$1(node) { 44033 var len = nodeLength(node); 44034 if (len === 0) { 44035 return true; 44036 } 44037 else if (!isText(node) && len === 1 && node.innerHTML === blankHTML) { 44038 // ex) <p><br></p>, <span><br></span> 44039 return true; 44040 } 44041 else if (lists.all(node.childNodes, isText) && node.innerHTML === '') { 44042 // ex) <p></p>, <span></span> 44043 return true; 44044 } 44045 return false; 44046 } 44047 /** 44048 * padding blankHTML if node is empty (for cursor position) 44049 */ 44050 function paddingBlankHTML(node) { 44051 if (!isVoid(node) && !nodeLength(node)) { 44052 node.innerHTML = blankHTML; 44053 } 44054 } 44055 /** 44056 * find nearest ancestor predicate hit 44057 * 44058 * @param {Node} node 44059 * @param {Function} pred - predicate function 44060 */ 44061 function ancestor(node, pred) { 44062 while (node) { 44063 if (pred(node)) { 44064 return node; 44065 } 44066 if (isEditable(node)) { 44067 break; 44068 } 44069 node = node.parentNode; 44070 } 44071 return null; 44072 } 44073 /** 44074 * find nearest ancestor only single child blood line and predicate hit 44075 * 44076 * @param {Node} node 44077 * @param {Function} pred - predicate function 44078 */ 44079 function singleChildAncestor(node, pred) { 44080 node = node.parentNode; 44081 while (node) { 44082 if (nodeLength(node) !== 1) { 44083 break; 44084 } 44085 if (pred(node)) { 44086 return node; 44087 } 44088 if (isEditable(node)) { 44089 break; 44090 } 44091 node = node.parentNode; 44092 } 44093 return null; 44094 } 44095 /** 44096 * returns new array of ancestor nodes (until predicate hit). 44097 * 44098 * @param {Node} node 44099 * @param {Function} [optional] pred - predicate function 44100 */ 44101 function listAncestor(node, pred) { 44102 pred = pred || func.fail; 44103 var ancestors = []; 44104 ancestor(node, function (el) { 44105 if (!isEditable(el)) { 44106 ancestors.push(el); 44107 } 44108 return pred(el); 44109 }); 44110 return ancestors; 44111 } 44112 /** 44113 * find farthest ancestor predicate hit 44114 */ 44115 function lastAncestor(node, pred) { 44116 var ancestors = listAncestor(node); 44117 return lists.last(ancestors.filter(pred)); 44118 } 44119 /** 44120 * returns common ancestor node between two nodes. 44121 * 44122 * @param {Node} nodeA 44123 * @param {Node} nodeB 44124 */ 44125 function commonAncestor(nodeA, nodeB) { 44126 var ancestors = listAncestor(nodeA); 44127 for (var n = nodeB; n; n = n.parentNode) { 44128 if (ancestors.indexOf(n) > -1) 44129 return n; 44130 } 44131 return null; // difference document area 44132 } 44133 /** 44134 * listing all previous siblings (until predicate hit). 44135 * 44136 * @param {Node} node 44137 * @param {Function} [optional] pred - predicate function 44138 */ 44139 function listPrev(node, pred) { 44140 pred = pred || func.fail; 44141 var nodes = []; 44142 while (node) { 44143 if (pred(node)) { 44144 break; 44145 } 44146 nodes.push(node); 44147 node = node.previousSibling; 44148 } 44149 return nodes; 44150 } 44151 /** 44152 * listing next siblings (until predicate hit). 44153 * 44154 * @param {Node} node 44155 * @param {Function} [pred] - predicate function 44156 */ 44157 function listNext(node, pred) { 44158 pred = pred || func.fail; 44159 var nodes = []; 44160 while (node) { 44161 if (pred(node)) { 44162 break; 44163 } 44164 nodes.push(node); 44165 node = node.nextSibling; 44166 } 44167 return nodes; 44168 } 44169 /** 44170 * listing descendant nodes 44171 * 44172 * @param {Node} node 44173 * @param {Function} [pred] - predicate function 44174 */ 44175 function listDescendant(node, pred) { 44176 var descendants = []; 44177 pred = pred || func.ok; 44178 // start DFS(depth first search) with node 44179 (function fnWalk(current) { 44180 if (node !== current && pred(current)) { 44181 descendants.push(current); 44182 } 44183 for (var idx = 0, len = current.childNodes.length; idx < len; idx++) { 44184 fnWalk(current.childNodes[idx]); 44185 } 44186 })(node); 44187 return descendants; 44188 } 44189 /** 44190 * wrap node with new tag. 44191 * 44192 * @param {Node} node 44193 * @param {Node} tagName of wrapper 44194 * @return {Node} - wrapper 44195 */ 44196 function wrap(node, wrapperName) { 44197 var parent = node.parentNode; 44198 var wrapper = $$1('<' + wrapperName + '>')[0]; 44199 parent.insertBefore(wrapper, node); 44200 wrapper.appendChild(node); 44201 return wrapper; 44202 } 44203 /** 44204 * insert node after preceding 44205 * 44206 * @param {Node} node 44207 * @param {Node} preceding - predicate function 44208 */ 44209 function insertAfter(node, preceding) { 44210 var next = preceding.nextSibling; 44211 var parent = preceding.parentNode; 44212 if (next) { 44213 parent.insertBefore(node, next); 44214 } 44215 else { 44216 parent.appendChild(node); 44217 } 44218 return node; 44219 } 44220 /** 44221 * append elements. 44222 * 44223 * @param {Node} node 44224 * @param {Collection} aChild 44225 */ 44226 function appendChildNodes(node, aChild) { 44227 $$1.each(aChild, function (idx, child) { 44228 node.appendChild(child); 44229 }); 44230 return node; 44231 } 44232 /** 44233 * returns whether boundaryPoint is left edge or not. 44234 * 44235 * @param {BoundaryPoint} point 44236 * @return {Boolean} 44237 */ 44238 function isLeftEdgePoint(point) { 44239 return point.offset === 0; 44240 } 44241 /** 44242 * returns whether boundaryPoint is right edge or not. 44243 * 44244 * @param {BoundaryPoint} point 44245 * @return {Boolean} 44246 */ 44247 function isRightEdgePoint(point) { 44248 return point.offset === nodeLength(point.node); 44249 } 44250 /** 44251 * returns whether boundaryPoint is edge or not. 44252 * 44253 * @param {BoundaryPoint} point 44254 * @return {Boolean} 44255 */ 44256 function isEdgePoint(point) { 44257 return isLeftEdgePoint(point) || isRightEdgePoint(point); 44258 } 44259 /** 44260 * returns whether node is left edge of ancestor or not. 44261 * 44262 * @param {Node} node 44263 * @param {Node} ancestor 44264 * @return {Boolean} 44265 */ 44266 function isLeftEdgeOf(node, ancestor) { 44267 while (node && node !== ancestor) { 44268 if (position(node) !== 0) { 44269 return false; 44270 } 44271 node = node.parentNode; 44272 } 44273 return true; 44274 } 44275 /** 44276 * returns whether node is right edge of ancestor or not. 44277 * 44278 * @param {Node} node 44279 * @param {Node} ancestor 44280 * @return {Boolean} 44281 */ 44282 function isRightEdgeOf(node, ancestor) { 44283 if (!ancestor) { 44284 return false; 44285 } 44286 while (node && node !== ancestor) { 44287 if (position(node) !== nodeLength(node.parentNode) - 1) { 44288 return false; 44289 } 44290 node = node.parentNode; 44291 } 44292 return true; 44293 } 44294 /** 44295 * returns whether point is left edge of ancestor or not. 44296 * @param {BoundaryPoint} point 44297 * @param {Node} ancestor 44298 * @return {Boolean} 44299 */ 44300 function isLeftEdgePointOf(point, ancestor) { 44301 return isLeftEdgePoint(point) && isLeftEdgeOf(point.node, ancestor); 44302 } 44303 /** 44304 * returns whether point is right edge of ancestor or not. 44305 * @param {BoundaryPoint} point 44306 * @param {Node} ancestor 44307 * @return {Boolean} 44308 */ 44309 function isRightEdgePointOf(point, ancestor) { 44310 return isRightEdgePoint(point) && isRightEdgeOf(point.node, ancestor); 44311 } 44312 /** 44313 * returns offset from parent. 44314 * 44315 * @param {Node} node 44316 */ 44317 function position(node) { 44318 var offset = 0; 44319 while ((node = node.previousSibling)) { 44320 offset += 1; 44321 } 44322 return offset; 44323 } 44324 function hasChildren(node) { 44325 return !!(node && node.childNodes && node.childNodes.length); 44326 } 44327 /** 44328 * returns previous boundaryPoint 44329 * 44330 * @param {BoundaryPoint} point 44331 * @param {Boolean} isSkipInnerOffset 44332 * @return {BoundaryPoint} 44333 */ 44334 function prevPoint(point, isSkipInnerOffset) { 44335 var node; 44336 var offset; 44337 if (point.offset === 0) { 44338 if (isEditable(point.node)) { 44339 return null; 44340 } 44341 node = point.node.parentNode; 44342 offset = position(point.node); 44343 } 44344 else if (hasChildren(point.node)) { 44345 node = point.node.childNodes[point.offset - 1]; 44346 offset = nodeLength(node); 44347 } 44348 else { 44349 node = point.node; 44350 offset = isSkipInnerOffset ? 0 : point.offset - 1; 44351 } 44352 return { 44353 node: node, 44354 offset: offset 44355 }; 44356 } 44357 /** 44358 * returns next boundaryPoint 44359 * 44360 * @param {BoundaryPoint} point 44361 * @param {Boolean} isSkipInnerOffset 44362 * @return {BoundaryPoint} 44363 */ 44364 function nextPoint(point, isSkipInnerOffset) { 44365 var node, offset; 44366 if (nodeLength(point.node) === point.offset) { 44367 if (isEditable(point.node)) { 44368 return null; 44369 } 44370 node = point.node.parentNode; 44371 offset = position(point.node) + 1; 44372 } 44373 else if (hasChildren(point.node)) { 44374 node = point.node.childNodes[point.offset]; 44375 offset = 0; 44376 } 44377 else { 44378 node = point.node; 44379 offset = isSkipInnerOffset ? nodeLength(point.node) : point.offset + 1; 44380 } 44381 return { 44382 node: node, 44383 offset: offset 44384 }; 44385 } 44386 /** 44387 * returns whether pointA and pointB is same or not. 44388 * 44389 * @param {BoundaryPoint} pointA 44390 * @param {BoundaryPoint} pointB 44391 * @return {Boolean} 44392 */ 44393 function isSamePoint(pointA, pointB) { 44394 return pointA.node === pointB.node && pointA.offset === pointB.offset; 44395 } 44396 /** 44397 * returns whether point is visible (can set cursor) or not. 44398 * 44399 * @param {BoundaryPoint} point 44400 * @return {Boolean} 44401 */ 44402 function isVisiblePoint(point) { 44403 if (isText(point.node) || !hasChildren(point.node) || isEmpty$1(point.node)) { 44404 return true; 44405 } 44406 var leftNode = point.node.childNodes[point.offset - 1]; 44407 var rightNode = point.node.childNodes[point.offset]; 44408 if ((!leftNode || isVoid(leftNode)) && (!rightNode || isVoid(rightNode))) { 44409 return true; 44410 } 44411 return false; 44412 } 44413 /** 44414 * @method prevPointUtil 44415 * 44416 * @param {BoundaryPoint} point 44417 * @param {Function} pred 44418 * @return {BoundaryPoint} 44419 */ 44420 function prevPointUntil(point, pred) { 44421 while (point) { 44422 if (pred(point)) { 44423 return point; 44424 } 44425 point = prevPoint(point); 44426 } 44427 return null; 44428 } 44429 /** 44430 * @method nextPointUntil 44431 * 44432 * @param {BoundaryPoint} point 44433 * @param {Function} pred 44434 * @return {BoundaryPoint} 44435 */ 44436 function nextPointUntil(point, pred) { 44437 while (point) { 44438 if (pred(point)) { 44439 return point; 44440 } 44441 point = nextPoint(point); 44442 } 44443 return null; 44444 } 44445 /** 44446 * returns whether point has character or not. 44447 * 44448 * @param {Point} point 44449 * @return {Boolean} 44450 */ 44451 function isCharPoint(point) { 44452 if (!isText(point.node)) { 44453 return false; 44454 } 44455 var ch = point.node.nodeValue.charAt(point.offset - 1); 44456 return ch && (ch !== ' ' && ch !== NBSP_CHAR); 44457 } 44458 /** 44459 * @method walkPoint 44460 * 44461 * @param {BoundaryPoint} startPoint 44462 * @param {BoundaryPoint} endPoint 44463 * @param {Function} handler 44464 * @param {Boolean} isSkipInnerOffset 44465 */ 44466 function walkPoint(startPoint, endPoint, handler, isSkipInnerOffset) { 44467 var point = startPoint; 44468 while (point) { 44469 handler(point); 44470 if (isSamePoint(point, endPoint)) { 44471 break; 44472 } 44473 var isSkipOffset = isSkipInnerOffset && 44474 startPoint.node !== point.node && 44475 endPoint.node !== point.node; 44476 point = nextPoint(point, isSkipOffset); 44477 } 44478 } 44479 /** 44480 * @method makeOffsetPath 44481 * 44482 * return offsetPath(array of offset) from ancestor 44483 * 44484 * @param {Node} ancestor - ancestor node 44485 * @param {Node} node 44486 */ 44487 function makeOffsetPath(ancestor, node) { 44488 var ancestors = listAncestor(node, func.eq(ancestor)); 44489 return ancestors.map(position).reverse(); 44490 } 44491 /** 44492 * @method fromOffsetPath 44493 * 44494 * return element from offsetPath(array of offset) 44495 * 44496 * @param {Node} ancestor - ancestor node 44497 * @param {array} offsets - offsetPath 44498 */ 44499 function fromOffsetPath(ancestor, offsets) { 44500 var current = ancestor; 44501 for (var i = 0, len = offsets.length; i < len; i++) { 44502 if (current.childNodes.length <= offsets[i]) { 44503 current = current.childNodes[current.childNodes.length - 1]; 44504 } 44505 else { 44506 current = current.childNodes[offsets[i]]; 44507 } 44508 } 44509 return current; 44510 } 44511 /** 44512 * @method splitNode 44513 * 44514 * split element or #text 44515 * 44516 * @param {BoundaryPoint} point 44517 * @param {Object} [options] 44518 * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false 44519 * @param {Boolean} [options.isNotSplitEdgePoint] - default: false 44520 * @param {Boolean} [options.isDiscardEmptySplits] - default: false 44521 * @return {Node} right node of boundaryPoint 44522 */ 44523 function splitNode(point, options) { 44524 var isSkipPaddingBlankHTML = options && options.isSkipPaddingBlankHTML; 44525 var isNotSplitEdgePoint = options && options.isNotSplitEdgePoint; 44526 var isDiscardEmptySplits = options && options.isDiscardEmptySplits; 44527 if (isDiscardEmptySplits) { 44528 isSkipPaddingBlankHTML = true; 44529 } 44530 // edge case 44531 if (isEdgePoint(point) && (isText(point.node) || isNotSplitEdgePoint)) { 44532 if (isLeftEdgePoint(point)) { 44533 return point.node; 44534 } 44535 else if (isRightEdgePoint(point)) { 44536 return point.node.nextSibling; 44537 } 44538 } 44539 // split #text 44540 if (isText(point.node)) { 44541 return point.node.splitText(point.offset); 44542 } 44543 else { 44544 var childNode = point.node.childNodes[point.offset]; 44545 var clone = insertAfter(point.node.cloneNode(false), point.node); 44546 appendChildNodes(clone, listNext(childNode)); 44547 if (!isSkipPaddingBlankHTML) { 44548 paddingBlankHTML(point.node); 44549 paddingBlankHTML(clone); 44550 } 44551 if (isDiscardEmptySplits) { 44552 if (isEmpty$1(point.node)) { 44553 remove(point.node); 44554 } 44555 if (isEmpty$1(clone)) { 44556 remove(clone); 44557 return point.node.nextSibling; 44558 } 44559 } 44560 return clone; 44561 } 44562 } 44563 /** 44564 * @method splitTree 44565 * 44566 * split tree by point 44567 * 44568 * @param {Node} root - split root 44569 * @param {BoundaryPoint} point 44570 * @param {Object} [options] 44571 * @param {Boolean} [options.isSkipPaddingBlankHTML] - default: false 44572 * @param {Boolean} [options.isNotSplitEdgePoint] - default: false 44573 * @return {Node} right node of boundaryPoint 44574 */ 44575 function splitTree(root, point, options) { 44576 // ex) [#text, <span>, <p>] 44577 var ancestors = listAncestor(point.node, func.eq(root)); 44578 if (!ancestors.length) { 44579 return null; 44580 } 44581 else if (ancestors.length === 1) { 44582 return splitNode(point, options); 44583 } 44584 return ancestors.reduce(function (node, parent) { 44585 if (node === point.node) { 44586 node = splitNode(point, options); 44587 } 44588 return splitNode({ 44589 node: parent, 44590 offset: node ? position(node) : nodeLength(parent) 44591 }, options); 44592 }); 44593 } 44594 /** 44595 * split point 44596 * 44597 * @param {Point} point 44598 * @param {Boolean} isInline 44599 * @return {Object} 44600 */ 44601 function splitPoint(point, isInline) { 44602 // find splitRoot, container 44603 // - inline: splitRoot is a child of paragraph 44604 // - block: splitRoot is a child of bodyContainer 44605 var pred = isInline ? isPara : isBodyContainer; 44606 var ancestors = listAncestor(point.node, pred); 44607 var topAncestor = lists.last(ancestors) || point.node; 44608 var splitRoot, container; 44609 if (pred(topAncestor)) { 44610 splitRoot = ancestors[ancestors.length - 2]; 44611 container = topAncestor; 44612 } 44613 else { 44614 splitRoot = topAncestor; 44615 container = splitRoot.parentNode; 44616 } 44617 // if splitRoot is exists, split with splitTree 44618 var pivot = splitRoot && splitTree(splitRoot, point, { 44619 isSkipPaddingBlankHTML: isInline, 44620 isNotSplitEdgePoint: isInline 44621 }); 44622 // if container is point.node, find pivot with point.offset 44623 if (!pivot && container === point.node) { 44624 pivot = point.node.childNodes[point.offset]; 44625 } 44626 return { 44627 rightNode: pivot, 44628 container: container 44629 }; 44630 } 44631 function create(nodeName) { 44632 return document.createElement(nodeName); 44633 } 44634 function createText(text) { 44635 return document.createTextNode(text); 44636 } 44637 /** 44638 * @method remove 44639 * 44640 * remove node, (isRemoveChild: remove child or not) 44641 * 44642 * @param {Node} node 44643 * @param {Boolean} isRemoveChild 44644 */ 44645 function remove(node, isRemoveChild) { 44646 if (!node || !node.parentNode) { 44647 return; 44648 } 44649 if (node.removeNode) { 44650 return node.removeNode(isRemoveChild); 44651 } 44652 var parent = node.parentNode; 44653 if (!isRemoveChild) { 44654 var nodes = []; 44655 for (var i = 0, len = node.childNodes.length; i < len; i++) { 44656 nodes.push(node.childNodes[i]); 44657 } 44658 for (var i = 0, len = nodes.length; i < len; i++) { 44659 parent.insertBefore(nodes[i], node); 44660 } 44661 } 44662 parent.removeChild(node); 44663 } 44664 /** 44665 * @method removeWhile 44666 * 44667 * @param {Node} node 44668 * @param {Function} pred 44669 */ 44670 function removeWhile(node, pred) { 44671 while (node) { 44672 if (isEditable(node) || !pred(node)) { 44673 break; 44674 } 44675 var parent = node.parentNode; 44676 remove(node); 44677 node = parent; 44678 } 44679 } 44680 /** 44681 * @method replace 44682 * 44683 * replace node with provided nodeName 44684 * 44685 * @param {Node} node 44686 * @param {String} nodeName 44687 * @return {Node} - new node 44688 */ 44689 function replace(node, nodeName) { 44690 if (node.nodeName.toUpperCase() === nodeName.toUpperCase()) { 44691 return node; 44692 } 44693 var newNode = create(nodeName); 44694 if (node.style.cssText) { 44695 newNode.style.cssText = node.style.cssText; 44696 } 44697 appendChildNodes(newNode, lists.from(node.childNodes)); 44698 insertAfter(newNode, node); 44699 remove(node); 44700 return newNode; 44701 } 44702 var isTextarea = makePredByNodeName('TEXTAREA'); 44703 /** 44704 * @param {jQuery} $node 44705 * @param {Boolean} [stripLinebreaks] - default: false 44706 */ 44707 function value($node, stripLinebreaks) { 44708 var val = isTextarea($node[0]) ? $node.val() : $node.html(); 44709 if (stripLinebreaks) { 44710 return val.replace(/[\n\r]/g, ''); 44711 } 44712 return val; 44713 } 44714 /** 44715 * @method html 44716 * 44717 * get the HTML contents of node 44718 * 44719 * @param {jQuery} $node 44720 * @param {Boolean} [isNewlineOnBlock] 44721 */ 44722 function html($node, isNewlineOnBlock) { 44723 var markup = value($node); 44724 if (isNewlineOnBlock) { 44725 var regexTag = /<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g; 44726 markup = markup.replace(regexTag, function (match, endSlash, name) { 44727 name = name.toUpperCase(); 44728 var isEndOfInlineContainer = /^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(name) && 44729 !!endSlash; 44730 var isBlockNode = /^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(name); 44731 return match + ((isEndOfInlineContainer || isBlockNode) ? '\n' : ''); 44732 }); 44733 markup = markup.trim(); 44734 } 44735 return markup; 44736 } 44737 function posFromPlaceholder(placeholder) { 44738 var $placeholder = $$1(placeholder); 44739 var pos = $placeholder.offset(); 44740 var height = $placeholder.outerHeight(true); // include margin 44741 return { 44742 left: pos.left, 44743 top: pos.top + height 44744 }; 44745 } 44746 function attachEvents($node, events) { 44747 Object.keys(events).forEach(function (key) { 44748 $node.on(key, events[key]); 44749 }); 44750 } 44751 function detachEvents($node, events) { 44752 Object.keys(events).forEach(function (key) { 44753 $node.off(key, events[key]); 44754 }); 44755 } 44756 /** 44757 * @method isCustomStyleTag 44758 * 44759 * assert if a node contains a "note-styletag" class, 44760 * which implies that's a custom-made style tag node 44761 * 44762 * @param {Node} an HTML DOM node 44763 */ 44764 function isCustomStyleTag(node) { 44765 return node && !isText(node) && lists.contains(node.classList, 'note-styletag'); 44766 } 44767 var dom = { 44768 /** @property {String} NBSP_CHAR */ 44769 NBSP_CHAR: NBSP_CHAR, 44770 /** @property {String} ZERO_WIDTH_NBSP_CHAR */ 44771 ZERO_WIDTH_NBSP_CHAR: ZERO_WIDTH_NBSP_CHAR, 44772 /** @property {String} blank */ 44773 blank: blankHTML, 44774 /** @property {String} emptyPara */ 44775 emptyPara: "<p>" + blankHTML + "</p>", 44776 makePredByNodeName: makePredByNodeName, 44777 isEditable: isEditable, 44778 isControlSizing: isControlSizing, 44779 isText: isText, 44780 isElement: isElement, 44781 isVoid: isVoid, 44782 isPara: isPara, 44783 isPurePara: isPurePara, 44784 isHeading: isHeading, 44785 isInline: isInline, 44786 isBlock: func.not(isInline), 44787 isBodyInline: isBodyInline, 44788 isBody: isBody, 44789 isParaInline: isParaInline, 44790 isPre: isPre, 44791 isList: isList, 44792 isTable: isTable, 44793 isData: isData, 44794 isCell: isCell, 44795 isBlockquote: isBlockquote, 44796 isBodyContainer: isBodyContainer, 44797 isAnchor: isAnchor, 44798 isDiv: makePredByNodeName('DIV'), 44799 isLi: isLi, 44800 isBR: makePredByNodeName('BR'), 44801 isSpan: makePredByNodeName('SPAN'), 44802 isB: makePredByNodeName('B'), 44803 isU: makePredByNodeName('U'), 44804 isS: makePredByNodeName('S'), 44805 isI: makePredByNodeName('I'), 44806 isImg: makePredByNodeName('IMG'), 44807 isTextarea: isTextarea, 44808 isEmpty: isEmpty$1, 44809 isEmptyAnchor: func.and(isAnchor, isEmpty$1), 44810 isClosestSibling: isClosestSibling, 44811 withClosestSiblings: withClosestSiblings, 44812 nodeLength: nodeLength, 44813 isLeftEdgePoint: isLeftEdgePoint, 44814 isRightEdgePoint: isRightEdgePoint, 44815 isEdgePoint: isEdgePoint, 44816 isLeftEdgeOf: isLeftEdgeOf, 44817 isRightEdgeOf: isRightEdgeOf, 44818 isLeftEdgePointOf: isLeftEdgePointOf, 44819 isRightEdgePointOf: isRightEdgePointOf, 44820 prevPoint: prevPoint, 44821 nextPoint: nextPoint, 44822 isSamePoint: isSamePoint, 44823 isVisiblePoint: isVisiblePoint, 44824 prevPointUntil: prevPointUntil, 44825 nextPointUntil: nextPointUntil, 44826 isCharPoint: isCharPoint, 44827 walkPoint: walkPoint, 44828 ancestor: ancestor, 44829 singleChildAncestor: singleChildAncestor, 44830 listAncestor: listAncestor, 44831 lastAncestor: lastAncestor, 44832 listNext: listNext, 44833 listPrev: listPrev, 44834 listDescendant: listDescendant, 44835 commonAncestor: commonAncestor, 44836 wrap: wrap, 44837 insertAfter: insertAfter, 44838 appendChildNodes: appendChildNodes, 44839 position: position, 44840 hasChildren: hasChildren, 44841 makeOffsetPath: makeOffsetPath, 44842 fromOffsetPath: fromOffsetPath, 44843 splitTree: splitTree, 44844 splitPoint: splitPoint, 44845 create: create, 44846 createText: createText, 44847 remove: remove, 44848 removeWhile: removeWhile, 44849 replace: replace, 44850 html: html, 44851 value: value, 44852 posFromPlaceholder: posFromPlaceholder, 44853 attachEvents: attachEvents, 44854 detachEvents: detachEvents, 44855 isCustomStyleTag: isCustomStyleTag 44856 }; 44857 44858 var Context = /** @class */ (function () { 44859 /** 44860 * @param {jQuery} $note 44861 * @param {Object} options 44862 */ 44863 function Context($note, options) { 44864 this.ui = $$1.summernote.ui; 44865 this.$note = $note; 44866 this.memos = {}; 44867 this.modules = {}; 44868 this.layoutInfo = {}; 44869 this.options = options; 44870 this.initialize(); 44871 } 44872 /** 44873 * create layout and initialize modules and other resources 44874 */ 44875 Context.prototype.initialize = function () { 44876 this.layoutInfo = this.ui.createLayout(this.$note, this.options); 44877 this._initialize(); 44878 this.$note.hide(); 44879 return this; 44880 }; 44881 /** 44882 * destroy modules and other resources and remove layout 44883 */ 44884 Context.prototype.destroy = function () { 44885 this._destroy(); 44886 this.$note.removeData('summernote'); 44887 this.ui.removeLayout(this.$note, this.layoutInfo); 44888 }; 44889 /** 44890 * destory modules and other resources and initialize it again 44891 */ 44892 Context.prototype.reset = function () { 44893 var disabled = this.isDisabled(); 44894 this.code(dom.emptyPara); 44895 this._destroy(); 44896 this._initialize(); 44897 if (disabled) { 44898 this.disable(); 44899 } 44900 }; 44901 Context.prototype._initialize = function () { 44902 var _this = this; 44903 // add optional buttons 44904 var buttons = $$1.extend({}, this.options.buttons);
44905 Object.keys(buttons).forEach(function (key) { 44906 _this.memo('button.' + key, buttons[key]); 44907 }); 44908 var modules = $$1.extend({}, this.options.modules, $$1.summernote.plugins || {}); 44909 // add and initialize modules 44910 Object.keys(modules).forEach(function (key) { 44911 _this.module(key, modules[key], true); 44912 }); 44913 Object.keys(this.modules).forEach(function (key) { 44914 _this.initializeModule(key); 44915 }); 44916 }; 44917 Context.prototype._destroy = function () { 44918 var _this = this; 44919 // destroy modules with reversed order 44920 Object.keys(this.modules).reverse().forEach(function (key) { 44921 _this.removeModule(key); 44922 }); 44923 Object.keys(this.memos).forEach(function (key) { 44924 _this.removeMemo(key); 44925 }); 44926 // trigger custom onDestroy callback 44927 this.triggerEvent('destroy', this); 44928 }; 44929 Context.prototype.code = function (html) { 44930 var isActivated = this.invoke('codeview.isActivated'); 44931 if (html === undefined) { 44932 this.invoke('codeview.sync'); 44933 return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html(); 44934 } 44935 else { 44936 if (isActivated) { 44937 this.layoutInfo.codable.val(html); 44938 } 44939 else { 44940 this.layoutInfo.editable.html(html); 44941 } 44942 this.$note.val(html); 44943 this.triggerEvent('change', html, this.layoutInfo.editable); 44944 } 44945 }; 44946 Context.prototype.isDisabled = function () { 44947 return this.layoutInfo.editable.attr('contenteditable') === 'false'; 44948 }; 44949 Context.prototype.enable = function () { 44950 this.layoutInfo.editable.attr('contenteditable', true); 44951 this.invoke('toolbar.activate', true); 44952 this.triggerEvent('disable', false); 44953 }; 44954 Context.prototype.disable = function () { 44955 // close codeview if codeview is opend 44956 if (this.invoke('codeview.isActivated')) { 44957 this.invoke('codeview.deactivate'); 44958 } 44959 this.layoutInfo.editable.attr('contenteditable', false); 44960 this.invoke('toolbar.deactivate', true); 44961 this.triggerEvent('disable', true); 44962 }; 44963 Context.prototype.triggerEvent = function () { 44964 var namespace = lists.head(arguments); 44965 var args = lists.tail(lists.from(arguments)); 44966 var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')]; 44967 if (callback) { 44968 callback.apply(this.$note[0], args); 44969 }
44970 this.$note.trigger('summernote.' + namespace, args); 44971 }; 44972 Context.prototype.initializeModule = function (key) { 44973 var module = this.modules[key]; 44974 module.shouldInitialize = module.shouldInitialize || func.ok; 44975 if (!module.shouldInitialize()) { 44976 return; 44977 } 44978 // initialize module 44979 if (module.initialize) { 44980 module.initialize(); 44981 } 44982 // attach events 44983 if (module.events) { 44984 dom.attachEvents(this.$note, module.events); 44985 } 44986 }; 44987 Context.prototype.module = function (key, ModuleClass, withoutIntialize) { 44988 if (arguments.length === 1) { 44989 return this.modules[key]; 44990 } 44991 this.modules[key] = new ModuleClass(this); 44992 if (!withoutIntialize) { 44993 this.initializeModule(key); 44994 } 44995 }; 44996 Context.prototype.removeModule = function (key) { 44997 var module = this.modules[key]; 44998 if (module.shouldInitialize()) { 44999 if (module.events) { 45000 dom.detachEvents(this.$note, module.events); 45001 } 45002 if (module.destroy) { 45003 module.destroy(); 45004 } 45005 } 45006 delete this.modules[key]; 45007 }; 45008 Context.prototype.memo = function (key, obj) { 45009 if (arguments.length === 1) { 45010 return this.memos[key]; 45011 } 45012 this.memos[key] = obj; 45013 }; 45014 Context.prototype.removeMemo = function (key) { 45015 if (this.memos[key] && this.memos[key].destroy) { 45016 this.memos[key].destroy(); 45017 } 45018 delete this.memos[key]; 45019 }; 45020 /** 45021 * Some buttons need to change their visual style immediately once they get pressed 45022 */ 45023 Context.prototype.createInvokeHandlerAndUpdateState = function (namespace, value) { 45024 var _this = this; 45025 return function (event) { 45026 _this.createInvokeHandler(namespace, value)(event); 45027 _this.invoke('buttons.updateCurrentStyle'); 45028 }; 45029 }; 45030 Context.prototype.createInvokeHandler = function (namespace, value) { 45031 var _this = this; 45032 return function (event) { 45033 event.preventDefault(); 45034 var $target = $$1(event.target); 45035 _this.invoke(namespace, value || $target.closest('[data-value]').data('value'), $target); 45036 }; 45037 }; 45038 Context.prototype.invoke = function () { 45039 var namespace = lists.head(arguments); 45040 var args = lists.tail(lists.from(arguments)); 45041 var splits = namespace.split('.'); 45042 var hasSeparator = splits.length > 1; 45043 var moduleName = hasSeparator && lists.head(splits); 45044 var methodName = hasSeparator ? lists.last(splits) : lists.head(splits); 45045 var module = this.modules[moduleName || 'editor']; 45046 if (!moduleName && this[methodName]) { 45047 return this[methodName].apply(this, args); 45048 } 45049 else if (module && module[methodName] && module.shouldInitialize()) { 45050 return module[methodName].apply(module, args); 45051 } 45052 }; 45053 return Context; 45054 }()); 45055 45056 $$1.fn.extend({ 45057 /** 45058 * Summernote API 45059 * 45060 * @param {Object|String} 45061 * @return {this} 45062 */ 45063 summernote: function () { 45064 var type = $$1.type(lists.head(arguments)); 45065 var isExternalAPICalled = type === 'string'; 45066 var hasInitOptions = type === 'object'; 45067 var options = $$1.extend({}, $$1.summernote.options, hasInitOptions ? lists.head(arguments) : {}); 45068 // Update options 45069 options.langInfo = $$1.extend(true, {}, $$1.summernote.lang['en-US'], $$1.summernote.lang[options.lang]); 45070 options.icons = $$1.extend(true, {}, $$1.summernote.options.icons, options.icons); 45071 options.tooltip = options.tooltip === 'auto' ? !env.isSupportTouch : options.tooltip; 45072 this.each(function (idx, note) { 45073 var $note = $$1(note); 45074 if (!$note.data('summernote')) { 45075 var context = new Context($note, options); 45076 $note.data('summernote', context); 45077 $note.data('summernote').triggerEvent('init', context.layoutInfo); 45078 } 45079 }); 45080 var $note = this.first(); 45081 if ($note.length) { 45082 var context = $note.data('summernote'); 45083 if (isExternalAPICalled) {
vendor: 3,407 bytes, lines 45084-45168
45084 return context.invoke.apply(context, lists.from(arguments)); 45085 } 45086 else if (options.focus) { 45087 context.invoke('editor.focus'); 45088 } 45089 } 45090 return this; 45091 } 45092 }); 45093 45094 /** 45095 * return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js 45096 * 45097 * @param {TextRange} textRange 45098 * @param {Boolean} isStart 45099 * @return {BoundaryPoint} 45100 * 45101 * @see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx 45102 */ 45103 function textRangeToPoint(textRange, isStart) { 45104 var container = textRange.parentElement(); 45105 var offset; 45106 var tester = document.body.createTextRange(); 45107 var prevContainer; 45108 var childNodes = lists.from(container.childNodes); 45109 for (offset = 0; offset < childNodes.length; offset++) { 45110 if (dom.isText(childNodes[offset])) { 45111 continue; 45112 } 45113 tester.moveToElementText(childNodes[offset]); 45114 if (tester.compareEndPoints('StartToStart', textRange) >= 0) { 45115 break; 45116 } 45117 prevContainer = childNodes[offset]; 45118 } 45119 if (offset !== 0 && dom.isText(childNodes[offset - 1])) { 45120 var textRangeStart = document.body.createTextRange(); 45121 var curTextNode = null; 45122 textRangeStart.moveToElementText(prevContainer || container); 45123 textRangeStart.collapse(!prevContainer); 45124 curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild; 45125 var pointTester = textRange.duplicate(); 45126 pointTester.setEndPoint('StartToStart', textRangeStart); 45127 var textCount = pointTester.text.replace(/[\r\n]/g, '').length; 45128 while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) { 45129 textCount -= curTextNode.nodeValue.length; 45130 curTextNode = curTextNode.nextSibling; 45131 } 45132 // [workaround] enforce IE to re-reference curTextNode, hack 45133 var dummy = curTextNode.nodeValue; // eslint-disable-line 45134 if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) && 45135 textCount === curTextNode.nodeValue.length) { 45136 textCount -= curTextNode.nodeValue.length; 45137 curTextNode = curTextNode.nextSibling; 45138 } 45139 container = curTextNode; 45140 offset = textCount; 45141 } 45142 return { 45143 cont: container, 45144 offset: offset 45145 }; 45146 } 45147 /** 45148 * return TextRange from boundary point (inspired by google closure-library) 45149 * @param {BoundaryPoint} point 45150 * @return {TextRange} 45151 */ 45152 function pointToTextRange(point) { 45153 var textRangeInfo = function (container, offset) { 45154 var node, isCollapseToStart; 45155 if (dom.isText(container)) { 45156 var prevTextNodes = dom.listPrev(container, func.not(dom.isText)); 45157 var prevContainer = lists.last(prevTextNodes).previousSibling; 45158 node = prevContainer || container.parentNode; 45159 offset += lists.sum(lists.tail(prevTextNodes), dom.nodeLength); 45160 isCollapseToStart = !prevContainer; 45161 } 45162 else { 45163 node = container.childNodes[offset] || container; 45164 if (dom.isText(node)) { 45165 return textRangeInfo(node, 0); 45166 } 45167 offset = 0; 45168 isCollapseToStart = false;
45169 } 45170 return { 45171 node: node, 45172 collapseToStart: isCollapseToStart, 45173 offset: offset 45174 }; 45175 }; 45176 var textRange = document.body.createTextRange(); 45177 var info = textRangeInfo(point.node, point.offset); 45178 textRange.moveToElementText(info.node); 45179 textRange.collapse(info.collapseToStart); 45180 textRange.moveStart('character', info.offset); 45181 return textRange; 45182 } 45183 /** 45184 * Wrapped Range 45185 * 45186 * @constructor 45187 * @param {Node} sc - start container 45188 * @param {Number} so - start offset 45189 * @param {Node} ec - end container 45190 * @param {Number} eo - end offset 45191 */ 45192 var WrappedRange = /** @class */ (function () { 45193 function WrappedRange(sc, so, ec, eo) { 45194 this.sc = sc; 45195 this.so = so; 45196 this.ec = ec; 45197 this.eo = eo; 45198 // isOnEditable: judge whether range is on editable or not 45199 this.isOnEditable = this.makeIsOn(dom.isEditable); 45200 // isOnList: judge whether range is on list node or not 45201 this.isOnList = this.makeIsOn(dom.isList); 45202 // isOnAnchor: judge whether range is on anchor node or not 45203 this.isOnAnchor = this.makeIsOn(dom.isAnchor); 45204 // isOnCell: judge whether range is on cell node or not 45205 this.isOnCell = this.makeIsOn(dom.isCell); 45206 // isOnData: judge whether range is on data node or not 45207 this.isOnData = this.makeIsOn(dom.isData); 45208 } 45209 // nativeRange: get nativeRange from sc, so, ec, eo 45210 WrappedRange.prototype.nativeRange = function () { 45211 if (env.isW3CRangeSupport) { 45212 var w3cRange = document.createRange(); 45213 w3cRange.setStart(this.sc, this.sc.data && this.so > this.sc.data.length ? 0 : this.so); 45214 w3cRange.setEnd(this.ec, this.sc.data ? Math.min(this.eo, this.sc.data.length) : this.eo); 45215 return w3cRange; 45216 } 45217 else { 45218 var textRange = pointToTextRange({ 45219 node: this.sc, 45220 offset: this.so 45221 }); 45222 textRange.setEndPoint('EndToEnd', pointToTextRange({ 45223 node: this.ec, 45224 offset: this.eo 45225 })); 45226 return textRange; 45227 } 45228 }; 45229 WrappedRange.prototype.getPoints = function () { 45230 return { 45231 sc: this.sc, 45232 so: this.so, 45233 ec: this.ec, 45234 eo: this.eo 45235 }; 45236 }; 45237 WrappedRange.prototype.getStartPoint = function () { 45238 return { 45239 node: this.sc, 45240 offset: this.so 45241 }; 45242 }; 45243 WrappedRange.prototype.getEndPoint = function () { 45244 return { 45245 node: this.ec, 45246 offset: this.eo 45247 }; 45248 }; 45249 /** 45250 * select update visible range 45251 */ 45252 WrappedRange.prototype.select = function () { 45253 var nativeRng = this.nativeRange(); 45254 if (env.isW3CRangeSupport) { 45255 var selection = document.getSelection(); 45256 if (selection.rangeCount > 0) { 45257 selection.removeAllRanges(); 45258 } 45259 selection.addRange(nativeRng); 45260 } 45261 else { 45262 nativeRng.select(); 45263 } 45264 return this; 45265 }; 45266 /** 45267 * Moves the scrollbar to start container(sc) of current range 45268 * 45269 * @return {WrappedRange} 45270 */ 45271 WrappedRange.prototype.scrollIntoView = function (container) { 45272 var height = $$1(container).height(); 45273 if (container.scrollTop + height < this.sc.offsetTop) { 45274 container.scrollTop += Math.abs(container.scrollTop + height - this.sc.offsetTop); 45275 } 45276 return this; 45277 }; 45278 /** 45279 * @return {WrappedRange} 45280 */ 45281 WrappedRange.prototype.normalize = function () { 45282 /** 45283 * @param {BoundaryPoint} point 45284 * @param {Boolean} isLeftToRight - true: prefer to choose right node 45285 * - false: prefer to choose left node 45286 * @return {BoundaryPoint} 45287 */ 45288 var getVisiblePoint = function (point, isLeftToRight) { 45289 // Just use the given point [XXX:Adhoc] 45290 // - case 01. if the point is on the middle of the node 45291 // - case 02. if the point is on the right edge and prefer to choose left node 45292 // - case 03. if the point is on the left edge and prefer to choose right node 45293 // - case 04. if the point is on the right edge and prefer to choose right node but the node is void 45294 // - case 05. if the point is on the left edge and prefer to choose left node but the node is void 45295 // - case 06. if the point is on the block node and there is no children 45296 if (dom.isVisiblePoint(point)) { 45297 if (!dom.isEdgePoint(point) || 45298 (dom.isRightEdgePoint(point) && !isLeftToRight) || 45299 (dom.isLeftEdgePoint(point) && isLeftToRight) || 45300 (dom.isRightEdgePoint(point) && isLeftToRight && dom.isVoid(point.node.nextSibling)) || 45301 (dom.isLeftEdgePoint(point) && !isLeftToRight && dom.isVoid(point.node.previousSibling)) || 45302 (dom.isBlock(point.node) && dom.isEmpty(point.node))) { 45303 return point; 45304 } 45305 } 45306 // point on block's edge 45307 var block = dom.ancestor(point.node, dom.isBlock); 45308 if (((dom.isLeftEdgePointOf(point, block) || dom.isVoid(dom.prevPoint(point).node)) && !isLeftToRight) || 45309 ((dom.isRightEdgePointOf(point, block) || dom.isVoid(dom.nextPoint(point).node)) && isLeftToRight)) { 45310 // returns point already on visible point 45311 if (dom.isVisiblePoint(point)) { 45312 return point; 45313 } 45314 // reverse direction 45315 isLeftToRight = !isLeftToRight; 45316 } 45317 var nextPoint = isLeftToRight ? dom.nextPointUntil(dom.nextPoint(point), dom.isVisiblePoint) 45318 : dom.prevPointUntil(dom.prevPoint(point), dom.isVisiblePoint); 45319 return nextPoint || point; 45320 }; 45321 var endPoint = getVisiblePoint(this.getEndPoint(), false); 45322 var startPoint = this.isCollapsed() ? endPoint : getVisiblePoint(this.getStartPoint(), true); 45323 return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); 45324 }; 45325 /** 45326 * returns matched nodes on range 45327 * 45328 * @param {Function} [pred] - predicate function 45329 * @param {Object} [options] 45330 * @param {Boolean} [options.includeAncestor] 45331 * @param {Boolean} [options.fullyContains] 45332 * @return {Node[]} 45333 */ 45334 WrappedRange.prototype.nodes = function (pred, options) { 45335 pred = pred || func.ok; 45336 var includeAncestor = options && options.includeAncestor; 45337 var fullyContains = options && options.fullyContains;
vendor: 17,235 bytes, lines 45338-45849
45338 // TODO compare points and sort 45339 var startPoint = this.getStartPoint(); 45340 var endPoint = this.getEndPoint(); 45341 var nodes = []; 45342 var leftEdgeNodes = []; 45343 dom.walkPoint(startPoint, endPoint, function (point) { 45344 if (dom.isEditable(point.node)) { 45345 return; 45346 } 45347 var node; 45348 if (fullyContains) { 45349 if (dom.isLeftEdgePoint(point)) { 45350 leftEdgeNodes.push(point.node); 45351 } 45352 if (dom.isRightEdgePoint(point) && lists.contains(leftEdgeNodes, point.node)) { 45353 node = point.node; 45354 } 45355 } 45356 else if (includeAncestor) { 45357 node = dom.ancestor(point.node, pred); 45358 } 45359 else { 45360 node = point.node; 45361 } 45362 if (node && pred(node)) { 45363 nodes.push(node); 45364 } 45365 }, true); 45366 return lists.unique(nodes); 45367 }; 45368 /** 45369 * returns commonAncestor of range 45370 * @return {Element} - commonAncestor 45371 */ 45372 WrappedRange.prototype.commonAncestor = function () { 45373 return dom.commonAncestor(this.sc, this.ec); 45374 }; 45375 /** 45376 * returns expanded range by pred 45377 * 45378 * @param {Function} pred - predicate function 45379 * @return {WrappedRange} 45380 */ 45381 WrappedRange.prototype.expand = function (pred) { 45382 var startAncestor = dom.ancestor(this.sc, pred); 45383 var endAncestor = dom.ancestor(this.ec, pred); 45384 if (!startAncestor && !endAncestor) { 45385 return new WrappedRange(this.sc, this.so, this.ec, this.eo); 45386 } 45387 var boundaryPoints = this.getPoints(); 45388 if (startAncestor) { 45389 boundaryPoints.sc = startAncestor; 45390 boundaryPoints.so = 0; 45391 } 45392 if (endAncestor) { 45393 boundaryPoints.ec = endAncestor; 45394 boundaryPoints.eo = dom.nodeLength(endAncestor); 45395 } 45396 return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo); 45397 }; 45398 /** 45399 * @param {Boolean} isCollapseToStart 45400 * @return {WrappedRange} 45401 */ 45402 WrappedRange.prototype.collapse = function (isCollapseToStart) { 45403 if (isCollapseToStart) { 45404 return new WrappedRange(this.sc, this.so, this.sc, this.so); 45405 } 45406 else { 45407 return new WrappedRange(this.ec, this.eo, this.ec, this.eo); 45408 } 45409 }; 45410 /** 45411 * splitText on range 45412 */ 45413 WrappedRange.prototype.splitText = function () { 45414 var isSameContainer = this.sc === this.ec; 45415 var boundaryPoints = this.getPoints(); 45416 if (dom.isText(this.ec) && !dom.isEdgePoint(this.getEndPoint())) { 45417 this.ec.splitText(this.eo); 45418 } 45419 if (dom.isText(this.sc) && !dom.isEdgePoint(this.getStartPoint())) { 45420 boundaryPoints.sc = this.sc.splitText(this.so); 45421 boundaryPoints.so = 0; 45422 if (isSameContainer) { 45423 boundaryPoints.ec = boundaryPoints.sc; 45424 boundaryPoints.eo = this.eo - this.so; 45425 } 45426 } 45427 return new WrappedRange(boundaryPoints.sc, boundaryPoints.so, boundaryPoints.ec, boundaryPoints.eo); 45428 }; 45429 /** 45430 * delete contents on range 45431 * @return {WrappedRange} 45432 */ 45433 WrappedRange.prototype.deleteContents = function () { 45434 if (this.isCollapsed()) { 45435 return this; 45436 } 45437 var rng = this.splitText(); 45438 var nodes = rng.nodes(null, { 45439 fullyContains: true 45440 }); 45441 // find new cursor point 45442 var point = dom.prevPointUntil(rng.getStartPoint(), function (point) { 45443 return !lists.contains(nodes, point.node); 45444 }); 45445 var emptyParents = []; 45446 $$1.each(nodes, function (idx, node) { 45447 // find empty parents 45448 var parent = node.parentNode; 45449 if (point.node !== parent && dom.nodeLength(parent) === 1) { 45450 emptyParents.push(parent); 45451 } 45452 dom.remove(node, false); 45453 }); 45454 // remove empty parents 45455 $$1.each(emptyParents, function (idx, node) { 45456 dom.remove(node, false); 45457 }); 45458 return new WrappedRange(point.node, point.offset, point.node, point.offset).normalize(); 45459 }; 45460 /** 45461 * makeIsOn: return isOn(pred) function 45462 */ 45463 WrappedRange.prototype.makeIsOn = function (pred) { 45464 return function () { 45465 var ancestor = dom.ancestor(this.sc, pred); 45466 return !!ancestor && (ancestor === dom.ancestor(this.ec, pred)); 45467 }; 45468 }; 45469 /** 45470 * @param {Function} pred 45471 * @return {Boolean} 45472 */ 45473 WrappedRange.prototype.isLeftEdgeOf = function (pred) { 45474 if (!dom.isLeftEdgePoint(this.getStartPoint())) { 45475 return false; 45476 } 45477 var node = dom.ancestor(this.sc, pred); 45478 return node && dom.isLeftEdgeOf(this.sc, node); 45479 }; 45480 /** 45481 * returns whether range was collapsed or not 45482 */ 45483 WrappedRange.prototype.isCollapsed = function () { 45484 return this.sc === this.ec && this.so === this.eo; 45485 }; 45486 /** 45487 * wrap inline nodes which children of body with paragraph 45488 * 45489 * @return {WrappedRange} 45490 */ 45491 WrappedRange.prototype.wrapBodyInlineWithPara = function () { 45492 if (dom.isBodyContainer(this.sc) && dom.isEmpty(this.sc)) { 45493 this.sc.innerHTML = dom.emptyPara; 45494 return new WrappedRange(this.sc.firstChild, 0, this.sc.firstChild, 0); 45495 } 45496 /** 45497 * [workaround] firefox often create range on not visible point. so normalize here. 45498 * - firefox: |<p>text</p>| 45499 * - chrome: <p>|text|</p> 45500 */ 45501 var rng = this.normalize(); 45502 if (dom.isParaInline(this.sc) || dom.isPara(this.sc)) { 45503 return rng; 45504 } 45505 // find inline top ancestor 45506 var topAncestor; 45507 if (dom.isInline(rng.sc)) { 45508 var ancestors = dom.listAncestor(rng.sc, func.not(dom.isInline)); 45509 topAncestor = lists.last(ancestors); 45510 if (!dom.isInline(topAncestor)) { 45511 topAncestor = ancestors[ancestors.length - 2] || rng.sc.childNodes[rng.so]; 45512 } 45513 } 45514 else { 45515 topAncestor = rng.sc.childNodes[rng.so > 0 ? rng.so - 1 : 0]; 45516 } 45517 // siblings not in paragraph 45518 var inlineSiblings = dom.listPrev(topAncestor, dom.isParaInline).reverse(); 45519 inlineSiblings = inlineSiblings.concat(dom.listNext(topAncestor.nextSibling, dom.isParaInline)); 45520 // wrap with paragraph 45521 if (inlineSiblings.length) { 45522 var para = dom.wrap(lists.head(inlineSiblings), 'p'); 45523 dom.appendChildNodes(para, lists.tail(inlineSiblings)); 45524 } 45525 return this.normalize(); 45526 }; 45527 /** 45528 * insert node at current cursor 45529 * 45530 * @param {Node} node 45531 * @return {Node} 45532 */ 45533 WrappedRange.prototype.insertNode = function (node) { 45534 var rng = this.wrapBodyInlineWithPara().deleteContents(); 45535 var info = dom.splitPoint(rng.getStartPoint(), dom.isInline(node)); 45536 if (info.rightNode) { 45537 info.rightNode.parentNode.insertBefore(node, info.rightNode); 45538 } 45539 else { 45540 info.container.appendChild(node); 45541 } 45542 return node; 45543 }; 45544 /** 45545 * insert html at current cursor 45546 */ 45547 WrappedRange.prototype.pasteHTML = function (markup) { 45548 var contentsContainer = $$1('<div></div>').html(markup)[0]; 45549 var childNodes = lists.from(contentsContainer.childNodes); 45550 var rng = this.wrapBodyInlineWithPara().deleteContents(); 45551 if (rng.so > 0) { 45552 childNodes = childNodes.reverse(); 45553 } 45554 childNodes = childNodes.map(function (childNode) { 45555 return rng.insertNode(childNode); 45556 }); 45557 if (rng.so > 0) { 45558 childNodes = childNodes.reverse(); 45559 } 45560 return childNodes; 45561 }; 45562 /** 45563 * returns text in range 45564 * 45565 * @return {String} 45566 */ 45567 WrappedRange.prototype.toString = function () { 45568 var nativeRng = this.nativeRange(); 45569 return env.isW3CRangeSupport ? nativeRng.toString() : nativeRng.text; 45570 }; 45571 /** 45572 * returns range for word before cursor 45573 * 45574 * @param {Boolean} [findAfter] - find after cursor, default: false 45575 * @return {WrappedRange} 45576 */ 45577 WrappedRange.prototype.getWordRange = function (findAfter) { 45578 var endPoint = this.getEndPoint(); 45579 if (!dom.isCharPoint(endPoint)) { 45580 return this; 45581 } 45582 var startPoint = dom.prevPointUntil(endPoint, function (point) { 45583 return !dom.isCharPoint(point); 45584 }); 45585 if (findAfter) { 45586 endPoint = dom.nextPointUntil(endPoint, function (point) { 45587 return !dom.isCharPoint(point); 45588 }); 45589 } 45590 return new WrappedRange(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset); 45591 }; 45592 /** 45593 * create offsetPath bookmark 45594 * 45595 * @param {Node} editable 45596 */ 45597 WrappedRange.prototype.bookmark = function (editable) { 45598 return { 45599 s: { 45600 path: dom.makeOffsetPath(editable, this.sc), 45601 offset: this.so 45602 }, 45603 e: { 45604 path: dom.makeOffsetPath(editable, this.ec), 45605 offset: this.eo 45606 } 45607 }; 45608 }; 45609 /** 45610 * create offsetPath bookmark base on paragraph 45611 * 45612 * @param {Node[]} paras 45613 */ 45614 WrappedRange.prototype.paraBookmark = function (paras) { 45615 return { 45616 s: { 45617 path: lists.tail(dom.makeOffsetPath(lists.head(paras), this.sc)), 45618 offset: this.so 45619 }, 45620 e: { 45621 path: lists.tail(dom.makeOffsetPath(lists.last(paras), this.ec)), 45622 offset: this.eo 45623 } 45624 }; 45625 }; 45626 /** 45627 * getClientRects 45628 * @return {Rect[]} 45629 */ 45630 WrappedRange.prototype.getClientRects = function () { 45631 var nativeRng = this.nativeRange(); 45632 return nativeRng.getClientRects(); 45633 }; 45634 return WrappedRange; 45635 }()); 45636 /** 45637 * Data structure 45638 * * BoundaryPoint: a point of dom tree 45639 * * BoundaryPoints: two boundaryPoints corresponding to the start and the end of the Range 45640 * 45641 * See to http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Position 45642 */ 45643 var range = { 45644 /** 45645 * create Range Object From arguments or Browser Selection 45646 * 45647 * @param {Node} sc - start container 45648 * @param {Number} so - start offset 45649 * @param {Node} ec - end container 45650 * @param {Number} eo - end offset 45651 * @return {WrappedRange} 45652 */ 45653 create: function (sc, so, ec, eo) { 45654 if (arguments.length === 4) { 45655 return new WrappedRange(sc, so, ec, eo); 45656 } 45657 else if (arguments.length === 2) { // collapsed 45658 ec = sc; 45659 eo = so; 45660 return new WrappedRange(sc, so, ec, eo); 45661 } 45662 else { 45663 var wrappedRange = this.createFromSelection(); 45664 if (!wrappedRange && arguments.length === 1) { 45665 wrappedRange = this.createFromNode(arguments[0]); 45666 return wrappedRange.collapse(dom.emptyPara === arguments[0].innerHTML); 45667 } 45668 return wrappedRange; 45669 } 45670 }, 45671 createFromSelection: function () { 45672 var sc, so, ec, eo; 45673 if (env.isW3CRangeSupport) { 45674 var selection = document.getSelection(); 45675 if (!selection || selection.rangeCount === 0) { 45676 return null; 45677 } 45678 else if (dom.isBody(selection.anchorNode)) { 45679 // Firefox: returns entire body as range on initialization. 45680 // We won't never need it. 45681 return null; 45682 } 45683 var nativeRng = selection.getRangeAt(0); 45684 sc = nativeRng.startContainer; 45685 so = nativeRng.startOffset; 45686 ec = nativeRng.endContainer; 45687 eo = nativeRng.endOffset; 45688 } 45689 else { // IE8: TextRange 45690 var textRange = document.selection.createRange(); 45691 var textRangeEnd = textRange.duplicate(); 45692 textRangeEnd.collapse(false); 45693 var textRangeStart = textRange; 45694 textRangeStart.collapse(true); 45695 var startPoint = textRangeToPoint(textRangeStart, true); 45696 var endPoint = textRangeToPoint(textRangeEnd, false); 45697 // same visible point case: range was collapsed. 45698 if (dom.isText(startPoint.node) && dom.isLeftEdgePoint(startPoint) && 45699 dom.isTextNode(endPoint.node) && dom.isRightEdgePoint(endPoint) && 45700 endPoint.node.nextSibling === startPoint.node) { 45701 startPoint = endPoint; 45702 } 45703 sc = startPoint.cont; 45704 so = startPoint.offset; 45705 ec = endPoint.cont; 45706 eo = endPoint.offset; 45707 } 45708 return new WrappedRange(sc, so, ec, eo); 45709 }, 45710 /** 45711 * @method 45712 * 45713 * create WrappedRange from node 45714 * 45715 * @param {Node} node 45716 * @return {WrappedRange} 45717 */ 45718 createFromNode: function (node) { 45719 var sc = node; 45720 var so = 0; 45721 var ec = node; 45722 var eo = dom.nodeLength(ec); 45723 // browsers can't target a picture or void node 45724 if (dom.isVoid(sc)) { 45725 so = dom.listPrev(sc).length - 1; 45726 sc = sc.parentNode; 45727 } 45728 if (dom.isBR(ec)) { 45729 eo = dom.listPrev(ec).length - 1; 45730 ec = ec.parentNode; 45731 } 45732 else if (dom.isVoid(ec)) { 45733 eo = dom.listPrev(ec).length; 45734 ec = ec.parentNode; 45735 } 45736 return this.create(sc, so, ec, eo); 45737 }, 45738 /** 45739 * create WrappedRange from node after position 45740 * 45741 * @param {Node} node 45742 * @return {WrappedRange} 45743 */ 45744 createFromNodeBefore: function (node) { 45745 return this.createFromNode(node).collapse(true); 45746 }, 45747 /** 45748 * create WrappedRange from node after position 45749 * 45750 * @param {Node} node 45751 * @return {WrappedRange} 45752 */ 45753 createFromNodeAfter: function (node) { 45754 return this.createFromNode(node).collapse(); 45755 }, 45756 /** 45757 * @method 45758 * 45759 * create WrappedRange from bookmark 45760 * 45761 * @param {Node} editable 45762 * @param {Object} bookmark 45763 * @return {WrappedRange} 45764 */ 45765 createFromBookmark: function (editable, bookmark) { 45766 var sc = dom.fromOffsetPath(editable, bookmark.s.path); 45767 var so = bookmark.s.offset; 45768 var ec = dom.fromOffsetPath(editable, bookmark.e.path); 45769 var eo = bookmark.e.offset; 45770 return new WrappedRange(sc, so, ec, eo); 45771 }, 45772 /** 45773 * @method 45774 * 45775 * create WrappedRange from paraBookmark 45776 * 45777 * @param {Object} bookmark 45778 * @param {Node[]} paras 45779 * @return {WrappedRange} 45780 */ 45781 createFromParaBookmark: function (bookmark, paras) { 45782 var so = bookmark.s.offset; 45783 var eo = bookmark.e.offset; 45784 var sc = dom.fromOffsetPath(lists.head(paras), bookmark.s.path); 45785 var ec = dom.fromOffsetPath(lists.last(paras), bookmark.e.path); 45786 return new WrappedRange(sc, so, ec, eo); 45787 } 45788 }; 45789 45790 var KEY_MAP = { 45791 'BACKSPACE': 8, 45792 'TAB': 9, 45793 'ENTER': 13, 45794 'SPACE': 32, 45795 'DELETE': 46, 45796 // Arrow 45797 'LEFT': 37, 45798 'UP': 38, 45799 'RIGHT': 39, 45800 'DOWN': 40, 45801 // Number: 0-9 45802 'NUM0': 48, 45803 'NUM1': 49, 45804 'NUM2': 50, 45805 'NUM3': 51, 45806 'NUM4': 52, 45807 'NUM5': 53, 45808 'NUM6': 54, 45809 'NUM7': 55, 45810 'NUM8': 56, 45811 // Alphabet: a-z 45812 'B': 66, 45813 'E': 69, 45814 'I': 73, 45815 'J': 74, 45816 'K': 75, 45817 'L': 76, 45818 'R': 82, 45819 'S': 83, 45820 'U': 85, 45821 'V': 86, 45822 'Y': 89, 45823 'Z': 90, 45824 'SLASH': 191, 45825 'LEFTBRACKET': 219, 45826 'BACKSLASH': 220, 45827 'RIGHTBRACKET': 221 45828 }; 45829 /** 45830 * @class core.key 45831 * 45832 * Object for keycodes. 45833 * 45834 * @singleton 45835 * @alternateClassName key 45836 */ 45837 var key = { 45838 /** 45839 * @method isEdit 45840 * 45841 * @param {Number} keyCode 45842 * @return {Boolean} 45843 */ 45844 isEdit: function (keyCode) { 45845 return lists.contains([ 45846 KEY_MAP.BACKSPACE, 45847 KEY_MAP.TAB, 45848 KEY_MAP.ENTER, 45849 KEY_MAP.SPACE,
45850 KEY_MAP.DELETE, 45851 ], keyCode); 45852 }, 45853 /** 45854 * @method isMove 45855 * 45856 * @param {Number} keyCode 45857 * @return {Boolean} 45858 */ 45859 isMove: function (keyCode) { 45860 return lists.contains([ 45861 KEY_MAP.LEFT, 45862 KEY_MAP.UP, 45863 KEY_MAP.RIGHT, 45864 KEY_MAP.DOWN, 45865 ], keyCode); 45866 }, 45867 /** 45868 * @property {Object} nameFromCode 45869 * @property {String} nameFromCode.8 "BACKSPACE" 45870 */ 45871 nameFromCode: func.invertObject(KEY_MAP), 45872 code: KEY_MAP 45873 }; 45874 45875 /** 45876 * @method readFileAsDataURL 45877 * 45878 * read contents of file as representing URL 45879 * 45880 * @param {File} file 45881 * @return {Promise} - then: dataUrl 45882 */ 45883 function readFileAsDataURL(file) { 45884 return $$1.Deferred(function (deferred) { 45885 $$1.extend(new FileReader(), { 45886 onload: function (e) { 45887 var dataURL = e.target.result; 45888 deferred.resolve(dataURL); 45889 }, 45890 onerror: function (err) { 45891 deferred.reject(err); 45892 } 45893 }).readAsDataURL(file); 45894 }).promise(); 45895 } 45896 /** 45897 * @method createImage 45898 * 45899 * create `<image>` from url string 45900 * 45901 * @param {String} url 45902 * @return {Promise} - then: $image 45903 */ 45904 function createImage(url) { 45905 return $$1.Deferred(function (deferred) { 45906 var $img = $$1('<img>'); 45907 $img.one('load', function () { 45908 $img.off('error abort'); 45909 deferred.resolve($img); 45910 }).one('error abort', function () { 45911 $img.off('load').detach(); 45912 deferred.reject($img); 45913 }).css({ 45914 display: 'none' 45915 }).appendTo(document.body).attr('src', url); 45916 }).promise(); 45917 } 45918 45919 var History = /** @class */ (function () { 45920 function History($editable) { 45921 this.stack = []; 45922 this.stackOffset = -1; 45923 this.$editable = $editable; 45924 this.editable = $editable[0]; 45925 } 45926 History.prototype.makeSnapshot = function () { 45927 var rng = range.create(this.editable); 45928 var emptyBookmark = { s: { path: [], offset: 0 }, e: { path: [], offset: 0 } }; 45929 return { 45930 contents: this.$editable.html(), 45931 bookmark: ((rng && rng.isOnEditable()) ? rng.bookmark(this.editable) : emptyBookmark) 45932 }; 45933 }; 45934 History.prototype.applySnapshot = function (snapshot) { 45935 if (snapshot.contents !== null) { 45936 this.$editable.html(snapshot.contents); 45937 } 45938 if (snapshot.bookmark !== null) { 45939 range.createFromBookmark(this.editable, snapshot.bookmark).select(); 45940 } 45941 }; 45942 /** 45943 * @method rewind 45944 * Rewinds the history stack back to the first snapshot taken. 45945 * Leaves the stack intact, so that "Redo" can still be used. 45946 */ 45947 History.prototype.rewind = function () { 45948 // Create snap shot if not yet recorded 45949 if (this.$editable.html() !== this.stack[this.stackOffset].contents) { 45950 this.recordUndo(); 45951 } 45952 // Return to the first available snapshot. 45953 this.stackOffset = 0; 45954 // Apply that snapshot. 45955 this.applySnapshot(this.stack[this.stackOffset]); 45956 }; 45957 /** 45958 * @method commit 45959 * Resets history stack, but keeps current editor's content. 45960 */ 45961 History.prototype.commit = function () { 45962 // Clear the stack. 45963 this.stack = []; 45964 // Restore stackOffset to its original value. 45965 this.stackOffset = -1; 45966 // Record our first snapshot (of nothing). 45967 this.recordUndo(); 45968 }; 45969 /** 45970 * @method reset 45971 * Resets the history stack completely; reverting to an empty editor. 45972 */ 45973 History.prototype.reset = function () { 45974 // Clear the stack. 45975 this.stack = []; 45976 // Restore stackOffset to its original value. 45977 this.stackOffset = -1; 45978 // Clear the editable area. 45979 this.$editable.html(''); 45980 // Record our first snapshot (of nothing). 45981 this.recordUndo(); 45982 }; 45983 /** 45984 * undo 45985 */ 45986 History.prototype.undo = function () { 45987 // Create snap shot if not yet recorded 45988 if (this.$editable.html() !== this.stack[this.stackOffset].contents) { 45989 this.recordUndo(); 45990 } 45991 if (this.stackOffset > 0) { 45992 this.stackOffset--;
45993 this.applySnapshot(this.stack[this.stackOffset]); 45994 } 45995 }; 45996 /** 45997 * redo 45998 */ 45999 History.prototype.redo = function () { 46000 if (this.stack.length - 1 > this.stackOffset) { 46001 this.stackOffset++; 46002 this.applySnapshot(this.stack[this.stackOffset]); 46003 } 46004 }; 46005 /** 46006 * recorded undo 46007 */ 46008 History.prototype.recordUndo = function () { 46009 this.stackOffset++; 46010 // Wash out stack after stackOffset 46011 if (this.stack.length > this.stackOffset) { 46012 this.stack = this.stack.slice(0, this.stackOffset); 46013 } 46014 // Create new snapshot and push it to the end 46015 this.stack.push(this.makeSnapshot()); 46016 }; 46017 return History; 46018 }()); 46019 46020 var Style = /** @class */ (function () { 46021 function Style() { 46022 } 46023 /** 46024 * @method jQueryCSS 46025 * 46026 * [workaround] for old jQuery 46027 * passing an array of style properties to .css() 46028 * will result in an object of property-value pairs. 46029 * (compability with version < 1.9) 46030 * 46031 * @private 46032 * @param {jQuery} $obj 46033 * @param {Array} propertyNames - An array of one or more CSS properties. 46034 * @return {Object} 46035 */ 46036 Style.prototype.jQueryCSS = function ($obj, propertyNames) { 46037 if (env.jqueryVersion < 1.9) { 46038 var result_1 = {}; 46039 $$1.each(propertyNames, function (idx, propertyName) { 46040 result_1[propertyName] = $obj.css(propertyName); 46041 }); 46042 return result_1; 46043 } 46044 return $obj.css(propertyNames); 46045 }; 46046 /** 46047 * returns style object from node 46048 * 46049 * @param {jQuery} $node 46050 * @return {Object} 46051 */ 46052 Style.prototype.fromNode = function ($node) { 46053 var properties = ['font-family', 'font-size', 'text-align', 'list-style-type', 'line-height']; 46054 var styleInfo = this.jQueryCSS($node, properties) || {}; 46055 styleInfo['font-size'] = parseInt(styleInfo['font-size'], 10); 46056 return styleInfo; 46057 }; 46058 /** 46059 * paragraph level style 46060 * 46061 * @param {WrappedRange} rng 46062 * @param {Object} styleInfo 46063 */ 46064 Style.prototype.stylePara = function (rng, styleInfo) {
vendor: 4,328 bytes, lines 46065-46157
46065 $$1.each(rng.nodes(dom.isPara, { 46066 includeAncestor: true 46067 }), function (idx, para) { 46068 $$1(para).css(styleInfo); 46069 }); 46070 }; 46071 /** 46072 * insert and returns styleNodes on range. 46073 * 46074 * @param {WrappedRange} rng 46075 * @param {Object} [options] - options for styleNodes 46076 * @param {String} [options.nodeName] - default: `SPAN` 46077 * @param {Boolean} [options.expandClosestSibling] - default: `false` 46078 * @param {Boolean} [options.onlyPartialContains] - default: `false` 46079 * @return {Node[]} 46080 */ 46081 Style.prototype.styleNodes = function (rng, options) { 46082 rng = rng.splitText(); 46083 var nodeName = (options && options.nodeName) || 'SPAN'; 46084 var expandClosestSibling = !!(options && options.expandClosestSibling); 46085 var onlyPartialContains = !!(options && options.onlyPartialContains); 46086 if (rng.isCollapsed()) { 46087 return [rng.insertNode(dom.create(nodeName))]; 46088 } 46089 var pred = dom.makePredByNodeName(nodeName); 46090 var nodes = rng.nodes(dom.isText, { 46091 fullyContains: true 46092 }).map(function (text) { 46093 return dom.singleChildAncestor(text, pred) || dom.wrap(text, nodeName); 46094 }); 46095 if (expandClosestSibling) { 46096 if (onlyPartialContains) { 46097 var nodesInRange_1 = rng.nodes(); 46098 // compose with partial contains predication 46099 pred = func.and(pred, function (node) { 46100 return lists.contains(nodesInRange_1, node); 46101 }); 46102 } 46103 return nodes.map(function (node) { 46104 var siblings = dom.withClosestSiblings(node, pred); 46105 var head = lists.head(siblings); 46106 var tails = lists.tail(siblings); 46107 $$1.each(tails, function (idx, elem) { 46108 dom.appendChildNodes(head, elem.childNodes); 46109 dom.remove(elem); 46110 }); 46111 return lists.head(siblings); 46112 }); 46113 } 46114 else { 46115 return nodes; 46116 } 46117 }; 46118 /** 46119 * get current style on cursor 46120 * 46121 * @param {WrappedRange} rng 46122 * @return {Object} - object contains style properties. 46123 */ 46124 Style.prototype.current = function (rng) { 46125 var $cont = $$1(!dom.isElement(rng.sc) ? rng.sc.parentNode : rng.sc); 46126 var styleInfo = this.fromNode($cont); 46127 // document.queryCommandState for toggle state 46128 // [workaround] prevent Firefox nsresult: "0x80004005 (NS_ERROR_FAILURE)" 46129 try { 46130 styleInfo = $$1.extend(styleInfo, { 46131 'font-bold': document.queryCommandState('bold') ? 'bold' : 'normal', 46132 'font-italic': document.queryCommandState('italic') ? 'italic' : 'normal', 46133 'font-underline': document.queryCommandState('underline') ? 'underline' : 'normal', 46134 'font-subscript': document.queryCommandState('subscript') ? 'subscript' : 'normal', 46135 'font-superscript': document.queryCommandState('superscript') ? 'superscript' : 'normal', 46136 'font-strikethrough': document.queryCommandState('strikethrough') ? 'strikethrough' : 'normal', 46137 'font-family': document.queryCommandValue('fontname') || styleInfo['font-family'] 46138 }); 46139 } 46140 catch (e) { } 46141 // list-style-type to list-style(unordered, ordered) 46142 if (!rng.isOnList()) { 46143 styleInfo['list-style'] = 'none'; 46144 } 46145 else { 46146 var orderedTypes = ['circle', 'disc', 'disc-leading-zero', 'square']; 46147 var isUnordered = orderedTypes.indexOf(styleInfo['list-style-type']) > -1; 46148 styleInfo['list-style'] = isUnordered ? 'unordered' : 'ordered'; 46149 } 46150 var para = dom.ancestor(rng.sc, dom.isPara); 46151 if (para && para.style['line-height']) { 46152 styleInfo['line-height'] = para.style.lineHeight; 46153 } 46154 else { 46155 var lineHeight = parseInt(styleInfo['line-height'], 10) / parseInt(styleInfo['font-size'], 10); 46156 styleInfo['line-height'] = lineHeight.toFixed(1); 46157 }
46158 styleInfo.anchor = rng.isOnAnchor() && dom.ancestor(rng.sc, dom.isAnchor); 46159 styleInfo.ancestors = dom.listAncestor(rng.sc, dom.isEditable); 46160 styleInfo.range = rng; 46161 return styleInfo; 46162 }; 46163 return Style; 46164 }()); 46165 46166 var Bullet = /** @class */ (function () { 46167 function Bullet() { 46168 } 46169 /** 46170 * toggle ordered list 46171 */ 46172 Bullet.prototype.insertOrderedList = function (editable) { 46173 this.toggleList('OL', editable); 46174 }; 46175 /** 46176 * toggle unordered list 46177 */ 46178 Bullet.prototype.insertUnorderedList = function (editable) { 46179 this.toggleList('UL', editable); 46180 }; 46181 /** 46182 * indent 46183 */ 46184 Bullet.prototype.indent = function (editable) { 46185 var _this = this; 46186 var rng = range.create(editable).wrapBodyInlineWithPara(); 46187 var paras = rng.nodes(dom.isPara, { includeAncestor: true }); 46188 var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); 46189 $$1.each(clustereds, function (idx, paras) { 46190 var head = lists.head(paras); 46191 if (dom.isLi(head)) { 46192 var previousList_1 = _this.findList(head.previousSibling); 46193 if (previousList_1) { 46194 paras 46195 .map(function (para) { return previousList_1.appendChild(para); }); 46196 } 46197 else { 46198 _this.wrapList(paras, head.parentNode.nodeName); 46199 paras 46200 .map(function (para) { return para.parentNode; }) 46201 .map(function (para) { return _this.appendToPrevious(para); }); 46202 } 46203 } 46204 else { 46205 $$1.each(paras, function (idx, para) { 46206 $$1(para).css('marginLeft', function (idx, val) { 46207 return (parseInt(val, 10) || 0) + 25; 46208 }); 46209 }); 46210 } 46211 }); 46212 rng.select(); 46213 }; 46214 /** 46215 * outdent 46216 */ 46217 Bullet.prototype.outdent = function (editable) { 46218 var _this = this; 46219 var rng = range.create(editable).wrapBodyInlineWithPara(); 46220 var paras = rng.nodes(dom.isPara, { includeAncestor: true }); 46221 var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); 46222 $$1.each(clustereds, function (idx, paras) { 46223 var head = lists.head(paras); 46224 if (dom.isLi(head)) { 46225 _this.releaseList([paras]); 46226 } 46227 else { 46228 $$1.each(paras, function (idx, para) { 46229 $$1(para).css('marginLeft', function (idx, val) { 46230 val = (parseInt(val, 10) || 0); 46231 return val > 25 ? val - 25 : ''; 46232 }); 46233 }); 46234 } 46235 }); 46236 rng.select(); 46237 }; 46238 /** 46239 * toggle list 46240 * 46241 * @param {String} listName - OL or UL 46242 */ 46243 Bullet.prototype.toggleList = function (listName, editable) { 46244 var _this = this; 46245 var rng = range.create(editable).wrapBodyInlineWithPara(); 46246 var paras = rng.nodes(dom.isPara, { includeAncestor: true }); 46247 var bookmark = rng.paraBookmark(paras); 46248 var clustereds = lists.clusterBy(paras, func.peq2('parentNode')); 46249 // paragraph to list 46250 if (lists.find(paras, dom.isPurePara)) { 46251 var wrappedParas_1 = []; 46252 $$1.each(clustereds, function (idx, paras) { 46253 wrappedParas_1 = wrappedParas_1.concat(_this.wrapList(paras, listName)); 46254 }); 46255 paras = wrappedParas_1; 46256 // list to paragraph or change list style 46257 } 46258 else { 46259 var diffLists = rng.nodes(dom.isList, { 46260 includeAncestor: true 46261 }).filter(function (listNode) { 46262 return !$$1.nodeName(listNode, listName); 46263 }); 46264 if (diffLists.length) { 46265 $$1.each(diffLists, function (idx, listNode) { 46266 dom.replace(listNode, listName); 46267 }); 46268 } 46269 else { 46270 paras = this.releaseList(clustereds, true); 46271 } 46272 } 46273 range.createFromParaBookmark(bookmark, paras).select(); 46274 }; 46275 /** 46276 * @param {Node[]} paras 46277 * @param {String} listName 46278 * @return {Node[]} 46279 */ 46280 Bullet.prototype.wrapList = function (paras, listName) { 46281 var head = lists.head(paras); 46282 var last = lists.last(paras); 46283 var prevList = dom.isList(head.previousSibling) && head.previousSibling; 46284 var nextList = dom.isList(last.nextSibling) && last.nextSibling;
vendor: 18,288 bytes, lines 46285-46719
46285 var listNode = prevList || dom.insertAfter(dom.create(listName || 'UL'), last); 46286 // P to LI 46287 paras = paras.map(function (para) { 46288 return dom.isPurePara(para) ? dom.replace(para, 'LI') : para; 46289 }); 46290 // append to list(<ul>, <ol>) 46291 dom.appendChildNodes(listNode, paras); 46292 if (nextList) { 46293 dom.appendChildNodes(listNode, lists.from(nextList.childNodes)); 46294 dom.remove(nextList); 46295 } 46296 return paras; 46297 }; 46298 /** 46299 * @method releaseList 46300 * 46301 * @param {Array[]} clustereds 46302 * @param {Boolean} isEscapseToBody 46303 * @return {Node[]} 46304 */ 46305 Bullet.prototype.releaseList = function (clustereds, isEscapseToBody) { 46306 var _this = this; 46307 var releasedParas = []; 46308 $$1.each(clustereds, function (idx, paras) { 46309 var head = lists.head(paras); 46310 var last = lists.last(paras); 46311 var headList = isEscapseToBody ? dom.lastAncestor(head, dom.isList) : head.parentNode; 46312 var parentItem = headList.parentNode; 46313 if (headList.parentNode.nodeName === 'LI') { 46314 paras.map(function (para) { 46315 var newList = _this.findNextSiblings(para); 46316 if (parentItem.nextSibling) { 46317 parentItem.parentNode.insertBefore(para, parentItem.nextSibling); 46318 } 46319 else { 46320 parentItem.parentNode.appendChild(para); 46321 } 46322 if (newList.length) { 46323 _this.wrapList(newList, headList.nodeName); 46324 para.appendChild(newList[0].parentNode); 46325 } 46326 }); 46327 if (headList.children.length === 0) { 46328 parentItem.removeChild(headList); 46329 } 46330 if (parentItem.childNodes.length === 0) { 46331 parentItem.parentNode.removeChild(parentItem); 46332 } 46333 } 46334 else { 46335 var lastList = headList.childNodes.length > 1 ? dom.splitTree(headList, { 46336 node: last.parentNode, 46337 offset: dom.position(last) + 1 46338 }, { 46339 isSkipPaddingBlankHTML: true 46340 }) : null; 46341 var middleList = dom.splitTree(headList, { 46342 node: head.parentNode, 46343 offset: dom.position(head) 46344 }, { 46345 isSkipPaddingBlankHTML: true 46346 }); 46347 paras = isEscapseToBody ? dom.listDescendant(middleList, dom.isLi) 46348 : lists.from(middleList.childNodes).filter(dom.isLi); 46349 // LI to P 46350 if (isEscapseToBody || !dom.isList(headList.parentNode)) { 46351 paras = paras.map(function (para) { 46352 return dom.replace(para, 'P'); 46353 }); 46354 } 46355 $$1.each(lists.from(paras).reverse(), function (idx, para) { 46356 dom.insertAfter(para, headList); 46357 }); 46358 // remove empty lists 46359 var rootLists = lists.compact([headList, middleList, lastList]); 46360 $$1.each(rootLists, function (idx, rootList) { 46361 var listNodes = [rootList].concat(dom.listDescendant(rootList, dom.isList)); 46362 $$1.each(listNodes.reverse(), function (idx, listNode) { 46363 if (!dom.nodeLength(listNode)) { 46364 dom.remove(listNode, true); 46365 } 46366 }); 46367 }); 46368 } 46369 releasedParas = releasedParas.concat(paras); 46370 }); 46371 return releasedParas; 46372 }; 46373 /** 46374 * @method appendToPrevious 46375 * 46376 * Appends list to previous list item, if 46377 * none exist it wraps the list in a new list item. 46378 * 46379 * @param {HTMLNode} ListItem 46380 * @return {HTMLNode} 46381 */ 46382 Bullet.prototype.appendToPrevious = function (node) { 46383 return node.previousSibling 46384 ? dom.appendChildNodes(node.previousSibling, [node]) 46385 : this.wrapList([node], 'LI'); 46386 }; 46387 /** 46388 * @method findList 46389 * 46390 * Finds an existing list in list item 46391 * 46392 * @param {HTMLNode} ListItem 46393 * @return {Array[]} 46394 */ 46395 Bullet.prototype.findList = function (node) { 46396 return node 46397 ? lists.find(node.children, function (child) { return ['OL', 'UL'].indexOf(child.nodeName) > -1; }) 46398 : null; 46399 }; 46400 /** 46401 * @method findNextSiblings 46402 * 46403 * Finds all list item siblings that follow it 46404 * 46405 * @param {HTMLNode} ListItem 46406 * @return {HTMLNode} 46407 */ 46408 Bullet.prototype.findNextSiblings = function (node) { 46409 var siblings = []; 46410 while (node.nextSibling) { 46411 siblings.push(node.nextSibling); 46412 node = node.nextSibling; 46413 } 46414 return siblings; 46415 }; 46416 return Bullet; 46417 }()); 46418 46419 /** 46420 * @class editing.Typing 46421 * 46422 * Typing 46423 * 46424 */ 46425 var Typing = /** @class */ (function () { 46426 function Typing(context) { 46427 // a Bullet instance to toggle lists off 46428 this.bullet = new Bullet(); 46429 this.options = context.options; 46430 } 46431 /** 46432 * insert tab 46433 * 46434 * @param {WrappedRange} rng 46435 * @param {Number} tabsize 46436 */ 46437 Typing.prototype.insertTab = function (rng, tabsize) { 46438 var tab = dom.createText(new Array(tabsize + 1).join(dom.NBSP_CHAR)); 46439 rng = rng.deleteContents(); 46440 rng.insertNode(tab, true); 46441 rng = range.create(tab, tabsize); 46442 rng.select(); 46443 }; 46444 /** 46445 * insert paragraph 46446 * 46447 * @param {jQuery} $editable 46448 * @param {WrappedRange} rng Can be used in unit tests to "mock" the range 46449 * 46450 * blockquoteBreakingLevel 46451 * 0 - No break, the new paragraph remains inside the quote 46452 * 1 - Break the first blockquote in the ancestors list 46453 * 2 - Break all blockquotes, so that the new paragraph is not quoted (this is the default) 46454 */ 46455 Typing.prototype.insertParagraph = function (editable, rng) { 46456 rng = rng || range.create(editable); 46457 // deleteContents on range. 46458 rng = rng.deleteContents(); 46459 // Wrap range if it needs to be wrapped by paragraph 46460 rng = rng.wrapBodyInlineWithPara(); 46461 // finding paragraph 46462 var splitRoot = dom.ancestor(rng.sc, dom.isPara); 46463 var nextPara; 46464 // on paragraph: split paragraph 46465 if (splitRoot) { 46466 // if it is an empty line with li 46467 if (dom.isEmpty(splitRoot) && dom.isLi(splitRoot)) { 46468 // toogle UL/OL and escape 46469 this.bullet.toggleList(splitRoot.parentNode.nodeName); 46470 return; 46471 } 46472 else { 46473 var blockquote = null; 46474 if (this.options.blockquoteBreakingLevel === 1) { 46475 blockquote = dom.ancestor(splitRoot, dom.isBlockquote); 46476 } 46477 else if (this.options.blockquoteBreakingLevel === 2) { 46478 blockquote = dom.lastAncestor(splitRoot, dom.isBlockquote); 46479 } 46480 if (blockquote) { 46481 // We're inside a blockquote and options ask us to break it 46482 nextPara = $$1(dom.emptyPara)[0]; 46483 // If the split is right before a <br>, remove it so that there's no "empty line" 46484 // after the split in the new blockquote created 46485 if (dom.isRightEdgePoint(rng.getStartPoint()) && dom.isBR(rng.sc.nextSibling)) { 46486 $$1(rng.sc.nextSibling).remove(); 46487 } 46488 var split = dom.splitTree(blockquote, rng.getStartPoint(), { isDiscardEmptySplits: true }); 46489 if (split) { 46490 split.parentNode.insertBefore(nextPara, split); 46491 } 46492 else { 46493 dom.insertAfter(nextPara, blockquote); // There's no split if we were at the end of the blockquote 46494 } 46495 } 46496 else { 46497 nextPara = dom.splitTree(splitRoot, rng.getStartPoint()); 46498 // not a blockquote, just insert the paragraph 46499 var emptyAnchors = dom.listDescendant(splitRoot, dom.isEmptyAnchor); 46500 emptyAnchors = emptyAnchors.concat(dom.listDescendant(nextPara, dom.isEmptyAnchor)); 46501 $$1.each(emptyAnchors, function (idx, anchor) { 46502 dom.remove(anchor); 46503 }); 46504 // replace empty heading, pre or custom-made styleTag with P tag 46505 if ((dom.isHeading(nextPara) || dom.isPre(nextPara) || dom.isCustomStyleTag(nextPara)) && dom.isEmpty(nextPara)) { 46506 nextPara = dom.replace(nextPara, 'p'); 46507 } 46508 } 46509 } 46510 // no paragraph: insert empty paragraph 46511 } 46512 else { 46513 var next = rng.sc.childNodes[rng.so]; 46514 nextPara = $$1(dom.emptyPara)[0]; 46515 if (next) { 46516 rng.sc.insertBefore(nextPara, next); 46517 } 46518 else { 46519 rng.sc.appendChild(nextPara); 46520 } 46521 } 46522 range.create(nextPara, 0).normalize().select().scrollIntoView(editable); 46523 }; 46524 return Typing; 46525 }()); 46526 46527 /** 46528 * @class Create a virtual table to create what actions to do in change. 46529 * @param {object} startPoint Cell selected to apply change. 46530 * @param {enum} where Where change will be applied Row or Col. Use enum: TableResultAction.where 46531 * @param {enum} action Action to be applied. Use enum: TableResultAction.requestAction 46532 * @param {object} domTable Dom element of table to make changes. 46533 */ 46534 var TableResultAction = function (startPoint, where, action, domTable) { 46535 var _startPoint = { 'colPos': 0, 'rowPos': 0 }; 46536 var _virtualTable = []; 46537 var _actionCellList = []; 46538 /// /////////////////////////////////////////// 46539 // Private functions 46540 /// /////////////////////////////////////////// 46541 /** 46542 * Set the startPoint of action. 46543 */ 46544 function setStartPoint() { 46545 if (!startPoint || !startPoint.tagName || (startPoint.tagName.toLowerCase() !== 'td' && startPoint.tagName.toLowerCase() !== 'th')) { 46546 console.error('Impossible to identify start Cell point.', startPoint); 46547 return; 46548 } 46549 _startPoint.colPos = startPoint.cellIndex; 46550 if (!startPoint.parentElement || !startPoint.parentElement.tagName || startPoint.parentElement.tagName.toLowerCase() !== 'tr') { 46551 console.error('Impossible to identify start Row point.', startPoint); 46552 return; 46553 } 46554 _startPoint.rowPos = startPoint.parentElement.rowIndex; 46555 } 46556 /** 46557 * Define virtual table position info object. 46558 * 46559 * @param {int} rowIndex Index position in line of virtual table. 46560 * @param {int} cellIndex Index position in column of virtual table. 46561 * @param {object} baseRow Row affected by this position. 46562 * @param {object} baseCell Cell affected by this position. 46563 * @param {bool} isSpan Inform if it is an span cell/row. 46564 */ 46565 function setVirtualTablePosition(rowIndex, cellIndex, baseRow, baseCell, isRowSpan, isColSpan, isVirtualCell) { 46566 var objPosition = { 46567 'baseRow': baseRow, 46568 'baseCell': baseCell, 46569 'isRowSpan': isRowSpan, 46570 'isColSpan': isColSpan, 46571 'isVirtual': isVirtualCell 46572 }; 46573 if (!_virtualTable[rowIndex]) { 46574 _virtualTable[rowIndex] = []; 46575 } 46576 _virtualTable[rowIndex][cellIndex] = objPosition; 46577 } 46578 /** 46579 * Create action cell object. 46580 * 46581 * @param {object} virtualTableCellObj Object of specific position on virtual table. 46582 * @param {enum} resultAction Action to be applied in that item. 46583 */ 46584 function getActionCell(virtualTableCellObj, resultAction, virtualRowPosition, virtualColPosition) { 46585 return { 46586 'baseCell': virtualTableCellObj.baseCell, 46587 'action': resultAction, 46588 'virtualTable': { 46589 'rowIndex': virtualRowPosition, 46590 'cellIndex': virtualColPosition 46591 } 46592 }; 46593 } 46594 /** 46595 * Recover free index of row to append Cell. 46596 * 46597 * @param {int} rowIndex Index of row to find free space. 46598 * @param {int} cellIndex Index of cell to find free space in table. 46599 */ 46600 function recoverCellIndex(rowIndex, cellIndex) { 46601 if (!_virtualTable[rowIndex]) { 46602 return cellIndex; 46603 } 46604 if (!_virtualTable[rowIndex][cellIndex]) { 46605 return cellIndex; 46606 } 46607 var newCellIndex = cellIndex; 46608 while (_virtualTable[rowIndex][newCellIndex]) { 46609 newCellIndex++; 46610 if (!_virtualTable[rowIndex][newCellIndex]) { 46611 return newCellIndex; 46612 } 46613 } 46614 } 46615 /** 46616 * Recover info about row and cell and add information to virtual table. 46617 * 46618 * @param {object} row Row to recover information. 46619 * @param {object} cell Cell to recover information. 46620 */ 46621 function addCellInfoToVirtual(row, cell) { 46622 var cellIndex = recoverCellIndex(row.rowIndex, cell.cellIndex); 46623 var cellHasColspan = (cell.colSpan > 1); 46624 var cellHasRowspan = (cell.rowSpan > 1); 46625 var isThisSelectedCell = (row.rowIndex === _startPoint.rowPos && cell.cellIndex === _startPoint.colPos); 46626 setVirtualTablePosition(row.rowIndex, cellIndex, row, cell, cellHasRowspan, cellHasColspan, false); 46627 // Add span rows to virtual Table. 46628 var rowspanNumber = cell.attributes.rowSpan ? parseInt(cell.attributes.rowSpan.value, 10) : 0; 46629 if (rowspanNumber > 1) { 46630 for (var rp = 1; rp < rowspanNumber; rp++) { 46631 var rowspanIndex = row.rowIndex + rp; 46632 adjustStartPoint(rowspanIndex, cellIndex, cell, isThisSelectedCell); 46633 setVirtualTablePosition(rowspanIndex, cellIndex, row, cell, true, cellHasColspan, true); 46634 } 46635 } 46636 // Add span cols to virtual table. 46637 var colspanNumber = cell.attributes.colSpan ? parseInt(cell.attributes.colSpan.value, 10) : 0; 46638 if (colspanNumber > 1) { 46639 for (var cp = 1; cp < colspanNumber; cp++) { 46640 var cellspanIndex = recoverCellIndex(row.rowIndex, (cellIndex + cp)); 46641 adjustStartPoint(row.rowIndex, cellspanIndex, cell, isThisSelectedCell); 46642 setVirtualTablePosition(row.rowIndex, cellspanIndex, row, cell, cellHasRowspan, true, true); 46643 } 46644 } 46645 } 46646 /** 46647 * Process validation and adjust of start point if needed 46648 * 46649 * @param {int} rowIndex 46650 * @param {int} cellIndex 46651 * @param {object} cell 46652 * @param {bool} isSelectedCell 46653 */ 46654 function adjustStartPoint(rowIndex, cellIndex, cell, isSelectedCell) { 46655 if (rowIndex === _startPoint.rowPos && _startPoint.colPos >= cell.cellIndex && cell.cellIndex <= cellIndex && !isSelectedCell) { 46656 _startPoint.colPos++; 46657 } 46658 } 46659 /** 46660 * Create virtual table of cells with all cells, including span cells. 46661 */ 46662 function createVirtualTable() { 46663 var rows = domTable.rows; 46664 for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) { 46665 var cells = rows[rowIndex].cells; 46666 for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) { 46667 addCellInfoToVirtual(rows[rowIndex], cells[cellIndex]); 46668 } 46669 } 46670 } 46671 /** 46672 * Get action to be applied on the cell. 46673 * 46674 * @param {object} cell virtual table cell to apply action 46675 */ 46676 function getDeleteResultActionToCell(cell) { 46677 switch (where) { 46678 case TableResultAction.where.Column: 46679 if (cell.isColSpan) { 46680 return TableResultAction.resultAction.SubtractSpanCount; 46681 } 46682 break; 46683 case TableResultAction.where.Row: 46684 if (!cell.isVirtual && cell.isRowSpan) { 46685 return TableResultAction.resultAction.AddCell; 46686 } 46687 else if (cell.isRowSpan) { 46688 return TableResultAction.resultAction.SubtractSpanCount; 46689 } 46690 break; 46691 } 46692 return TableResultAction.resultAction.RemoveCell; 46693 } 46694 /** 46695 * Get action to be applied on the cell. 46696 * 46697 * @param {object} cell virtual table cell to apply action 46698 */ 46699 function getAddResultActionToCell(cell) { 46700 switch (where) { 46701 case TableResultAction.where.Column: 46702 if (cell.isColSpan) { 46703 return TableResultAction.resultAction.SumSpanCount; 46704 } 46705 else if (cell.isRowSpan && cell.isVirtual) { 46706 return TableResultAction.resultAction.Ignore; 46707 } 46708 break; 46709 case TableResultAction.where.Row: 46710 if (cell.isRowSpan) { 46711 return TableResultAction.resultAction.SumSpanCount; 46712 } 46713 else if (cell.isColSpan && cell.isVirtual) { 46714 return TableResultAction.resultAction.Ignore; 46715 } 46716 break; 46717 } 46718 return TableResultAction.resultAction.AddCell; 46719 }
46720 function init() { 46721 setStartPoint(); 46722 createVirtualTable(); 46723 } 46724 /// /////////////////////////////////////////// 46725 // Public functions 46726 /// /////////////////////////////////////////// 46727 /** 46728 * Recover array os what to do in table. 46729 */ 46730 this.getActionList = function () { 46731 var fixedRow = (where === TableResultAction.where.Row) ? _startPoint.rowPos : -1; 46732 var fixedCol = (where === TableResultAction.where.Column) ? _startPoint.colPos : -1; 46733 var actualPosition = 0; 46734 var canContinue = true; 46735 while (canContinue) { 46736 var rowPosition = (fixedRow >= 0) ? fixedRow : actualPosition; 46737 var colPosition = (fixedCol >= 0) ? fixedCol : actualPosition; 46738 var row = _virtualTable[rowPosition]; 46739 if (!row) { 46740 canContinue = false; 46741 return _actionCellList; 46742 } 46743 var cell = row[colPosition]; 46744 if (!cell) { 46745 canContinue = false; 46746 return _actionCellList; 46747 } 46748 // Define action to be applied in this cell 46749 var resultAction = TableResultAction.resultAction.Ignore; 46750 switch (action) { 46751 case TableResultAction.requestAction.Add: 46752 resultAction = getAddResultActionToCell(cell); 46753 break; 46754 case TableResultAction.requestAction.Delete: 46755 resultAction = getDeleteResultActionToCell(cell); 46756 break; 46757 } 46758 _actionCellList.push(getActionCell(cell, resultAction, rowPosition, colPosition)); 46759 actualPosition++; 46760 } 46761 return _actionCellList; 46762 }; 46763 init(); 46764 }; 46765 /** 46766 * 46767 * Where action occours enum. 46768 */ 46769 TableResultAction.where = { 'Row': 0, 'Column': 1 }; 46770 /** 46771 * 46772 * Requested action to apply enum. 46773 */ 46774 TableResultAction.requestAction = { 'Add': 0, 'Delete': 1 }; 46775 /** 46776 * 46777 * Result action to be executed enum. 46778 */ 46779 TableResultAction.resultAction = { 'Ignore': 0, 'SubtractSpanCount': 1, 'RemoveCell': 2, 'AddCell': 3, 'SumSpanCount': 4 }; 46780 /** 46781 * 46782 * @class editing.Table 46783 * 46784 * Table 46785 * 46786 */ 46787 var Table = /** @class */ (function () { 46788 function Table() { 46789 } 46790 /** 46791 * handle tab key 46792 * 46793 * @param {WrappedRange} rng 46794 * @param {Boolean} isShift 46795 */ 46796 Table.prototype.tab = function (rng, isShift) { 46797 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 46798 var table = dom.ancestor(cell, dom.isTable); 46799 var cells = dom.listDescendant(table, dom.isCell); 46800 var nextCell = lists[isShift ? 'prev' : 'next'](cells, cell); 46801 if (nextCell) { 46802 range.create(nextCell, 0).select(); 46803 } 46804 }; 46805 /** 46806 * Add a new row 46807 * 46808 * @param {WrappedRange} rng 46809 * @param {String} position (top/bottom) 46810 * @return {Node} 46811 */ 46812 Table.prototype.addRow = function (rng, position) { 46813 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 46814 var currentTr = $$1(cell).closest('tr'); 46815 var trAttributes = this.recoverAttributes(currentTr); 46816 var html = $$1('<tr' + trAttributes + '></tr>'); 46817 var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Add, $$1(currentTr).closest('table')[0]); 46818 var actions = vTable.getActionList(); 46819 for (var idCell = 0; idCell < actions.length; idCell++) { 46820 var currentCell = actions[idCell]; 46821 var tdAttributes = this.recoverAttributes(currentCell.baseCell); 46822 switch (currentCell.action) { 46823 case TableResultAction.resultAction.AddCell: 46824 html.append('<td' + tdAttributes + '>' + dom.blank + '</td>'); 46825 break; 46826 case TableResultAction.resultAction.SumSpanCount: 46827 if (position === 'top') { 46828 var baseCellTr = currentCell.baseCell.parent; 46829 var isTopFromRowSpan = (!baseCellTr ? 0 : currentCell.baseCell.closest('tr').rowIndex) <= currentTr[0].rowIndex; 46830 if (isTopFromRowSpan) { 46831 var newTd = $$1('<div></div>').append($$1('<td' + tdAttributes + '>' + dom.blank + '</td>').removeAttr('rowspan')).html(); 46832 html.append(newTd); 46833 break; 46834 } 46835 } 46836 var rowspanNumber = parseInt(currentCell.baseCell.rowSpan, 10); 46837 rowspanNumber++; 46838 currentCell.baseCell.setAttribute('rowSpan', rowspanNumber); 46839 break; 46840 } 46841 } 46842 if (position === 'top') { 46843 currentTr.before(html); 46844 } 46845 else { 46846 var cellHasRowspan = (cell.rowSpan > 1); 46847 if (cellHasRowspan) { 46848 var lastTrIndex = currentTr[0].rowIndex + (cell.rowSpan - 2); 46849 $$1($$1(currentTr).parent().find('tr')[lastTrIndex]).after($$1(html)); 46850 return; 46851 } 46852 currentTr.after(html); 46853 } 46854 }; 46855 /** 46856 * Add a new col 46857 * 46858 * @param {WrappedRange} rng 46859 * @param {String} position (left/right) 46860 * @return {Node} 46861 */ 46862 Table.prototype.addCol = function (rng, position) { 46863 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 46864 var row = $$1(cell).closest('tr'); 46865 var rowsGroup = $$1(row).siblings(); 46866 rowsGroup.push(row); 46867 var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Add, $$1(row).closest('table')[0]); 46868 var actions = vTable.getActionList(); 46869 for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) { 46870 var currentCell = actions[actionIndex]; 46871 var tdAttributes = this.recoverAttributes(currentCell.baseCell); 46872 switch (currentCell.action) { 46873 case TableResultAction.resultAction.AddCell: 46874 if (position === 'right') { 46875 $$1(currentCell.baseCell).after('<td' + tdAttributes + '>' + dom.blank + '</td>'); 46876 } 46877 else { 46878 $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>'); 46879 } 46880 break; 46881 case TableResultAction.resultAction.SumSpanCount: 46882 if (position === 'right') { 46883 var colspanNumber = parseInt(currentCell.baseCell.colSpan, 10); 46884 colspanNumber++; 46885 currentCell.baseCell.setAttribute('colSpan', colspanNumber); 46886 } 46887 else { 46888 $$1(currentCell.baseCell).before('<td' + tdAttributes + '>' + dom.blank + '</td>'); 46889 } 46890 break; 46891 } 46892 } 46893 }; 46894 /* 46895 * Copy attributes from element. 46896 * 46897 * @param {object} Element to recover attributes. 46898 * @return {string} Copied string elements. 46899 */ 46900 Table.prototype.recoverAttributes = function (el) { 46901 var resultStr = ''; 46902 if (!el) { 46903 return resultStr; 46904 } 46905 var attrList = el.attributes || []; 46906 for (var i = 0; i < attrList.length; i++) { 46907 if (attrList[i].name.toLowerCase() === 'id') { 46908 continue; 46909 } 46910 if (attrList[i].specified) { 46911 resultStr += ' ' + attrList[i].name + '=\'' + attrList[i].value + '\''; 46912 } 46913 } 46914 return resultStr; 46915 }; 46916 /** 46917 * Delete current row 46918 * 46919 * @param {WrappedRange} rng 46920 * @return {Node} 46921 */ 46922 Table.prototype.deleteRow = function (rng) { 46923 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 46924 var row = $$1(cell).closest('tr');
46925 var cellPos = row.children('td, th').index($$1(cell)); 46926 var rowPos = row[0].rowIndex; 46927 var vTable = new TableResultAction(cell, TableResultAction.where.Row, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]); 46928 var actions = vTable.getActionList(); 46929 for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) { 46930 if (!actions[actionIndex]) { 46931 continue; 46932 } 46933 var baseCell = actions[actionIndex].baseCell; 46934 var virtualPosition = actions[actionIndex].virtualTable; 46935 var hasRowspan = (baseCell.rowSpan && baseCell.rowSpan > 1); 46936 var rowspanNumber = (hasRowspan) ? parseInt(baseCell.rowSpan, 10) : 0; 46937 switch (actions[actionIndex].action) { 46938 case TableResultAction.resultAction.Ignore: 46939 continue; 46940 case TableResultAction.resultAction.AddCell: 46941 var nextRow = row.next('tr')[0]; 46942 if (!nextRow) { 46943 continue; 46944 } 46945 var cloneRow = row[0].cells[cellPos]; 46946 if (hasRowspan) { 46947 if (rowspanNumber > 2) { 46948 rowspanNumber--; 46949 nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]); 46950 nextRow.cells[cellPos].setAttribute('rowSpan', rowspanNumber); 46951 nextRow.cells[cellPos].innerHTML = ''; 46952 } 46953 else if (rowspanNumber === 2) { 46954 nextRow.insertBefore(cloneRow, nextRow.cells[cellPos]); 46955 nextRow.cells[cellPos].removeAttribute('rowSpan'); 46956 nextRow.cells[cellPos].innerHTML = ''; 46957 } 46958 } 46959 continue; 46960 case TableResultAction.resultAction.SubtractSpanCount: 46961 if (hasRowspan) { 46962 if (rowspanNumber > 2) { 46963 rowspanNumber--; 46964 baseCell.setAttribute('rowSpan', rowspanNumber); 46965 if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) { 46966 baseCell.innerHTML = ''; 46967 } 46968 } 46969 else if (rowspanNumber === 2) { 46970 baseCell.removeAttribute('rowSpan'); 46971 if (virtualPosition.rowIndex !== rowPos && baseCell.cellIndex === cellPos) { 46972 baseCell.innerHTML = ''; 46973 } 46974 } 46975 } 46976 continue; 46977 case TableResultAction.resultAction.RemoveCell: 46978 // Do not need remove cell because row will be deleted. 46979 continue; 46980 } 46981 } 46982 row.remove(); 46983 }; 46984 /** 46985 * Delete current col 46986 * 46987 * @param {WrappedRange} rng 46988 * @return {Node} 46989 */ 46990 Table.prototype.deleteCol = function (rng) { 46991 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 46992 var row = $$1(cell).closest('tr'); 46993 var cellPos = row.children('td, th').index($$1(cell)); 46994 var vTable = new TableResultAction(cell, TableResultAction.where.Column, TableResultAction.requestAction.Delete, $$1(row).closest('table')[0]); 46995 var actions = vTable.getActionList(); 46996 for (var actionIndex = 0; actionIndex < actions.length; actionIndex++) { 46997 if (!actions[actionIndex]) { 46998 continue; 46999 } 47000 switch (actions[actionIndex].action) { 47001 case TableResultAction.resultAction.Ignore: 47002 continue; 47003 case TableResultAction.resultAction.SubtractSpanCount: 47004 var baseCell = actions[actionIndex].baseCell; 47005 var hasColspan = (baseCell.colSpan && baseCell.colSpan > 1); 47006 if (hasColspan) { 47007 var colspanNumber = (baseCell.colSpan) ? parseInt(baseCell.colSpan, 10) : 0; 47008 if (colspanNumber > 2) { 47009 colspanNumber--; 47010 baseCell.setAttribute('colSpan', colspanNumber); 47011 if (baseCell.cellIndex === cellPos) { 47012 baseCell.innerHTML = ''; 47013 } 47014 } 47015 else if (colspanNumber === 2) { 47016 baseCell.removeAttribute('colSpan'); 47017 if (baseCell.cellIndex === cellPos) { 47018 baseCell.innerHTML = ''; 47019 } 47020 } 47021 } 47022 continue; 47023 case TableResultAction.resultAction.RemoveCell: 47024 dom.remove(actions[actionIndex].baseCell, true); 47025 continue; 47026 } 47027 } 47028 }; 47029 /** 47030 * create empty table element 47031 * 47032 * @param {Number} rowCount 47033 * @param {Number} colCount 47034 * @return {Node} 47035 */ 47036 Table.prototype.createTable = function (colCount, rowCount, options) { 47037 var tds = []; 47038 var tdHTML; 47039 for (var idxCol = 0; idxCol < colCount; idxCol++) { 47040 tds.push('<td>' + dom.blank + '</td>'); 47041 } 47042 tdHTML = tds.join(''); 47043 var trs = []; 47044 var trHTML; 47045 for (var idxRow = 0; idxRow < rowCount; idxRow++) { 47046 trs.push('<tr>' + tdHTML + '</tr>'); 47047 } 47048 trHTML = trs.join(''); 47049 var $table = $$1('<table>' + trHTML + '</table>'); 47050 if (options && options.tableClassName) { 47051 $table.addClass(options.tableClassName); 47052 } 47053 return $table[0]; 47054 }; 47055 /** 47056 * Delete current table 47057 * 47058 * @param {WrappedRange} rng 47059 * @return {Node} 47060 */ 47061 Table.prototype.deleteTable = function (rng) { 47062 var cell = dom.ancestor(rng.commonAncestor(), dom.isCell); 47063 $$1(cell).closest('table').remove(); 47064 }; 47065 return Table; 47066 }()); 47067 47068 var KEY_BOGUS = 'bogus'; 47069 /** 47070 * @class Editor 47071 */ 47072 var Editor = /** @class */ (function () { 47073 function Editor(context) { 47074 var _this = this; 47075 this.context = context; 47076 this.$note = context.layoutInfo.note; 47077 this.$editor = context.layoutInfo.editor; 47078 this.$editable = context.layoutInfo.editable; 47079 this.options = context.options; 47080 this.lang = this.options.langInfo; 47081 this.editable = this.$editable[0]; 47082 this.lastRange = null; 47083 this.style = new Style(); 47084 this.table = new Table(); 47085 this.typing = new Typing(context); 47086 this.bullet = new Bullet(); 47087 this.history = new History(this.$editable); 47088 this.context.memo('help.undo', this.lang.help.undo); 47089 this.context.memo('help.redo', this.lang.help.redo); 47090 this.context.memo('help.tab', this.lang.help.tab); 47091 this.context.memo('help.untab', this.lang.help.untab); 47092 this.context.memo('help.insertParagraph', this.lang.help.insertParagraph); 47093 this.context.memo('help.insertOrderedList', this.lang.help.insertOrderedList); 47094 this.context.memo('help.insertUnorderedList', this.lang.help.insertUnorderedList); 47095 this.context.memo('help.indent', this.lang.help.indent); 47096 this.context.memo('help.outdent', this.lang.help.outdent); 47097 this.context.memo('help.formatPara', this.lang.help.formatPara); 47098 this.context.memo('help.insertHorizontalRule', this.lang.help.insertHorizontalRule); 47099 this.context.memo('help.fontName', this.lang.help.fontName); 47100 // native commands(with execCommand), generate function for execCommand 47101 var commands = [ 47102 'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 47103 'justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull', 47104 'formatBlock', 'removeFormat', 'backColor', 47105 ]; 47106 for (var idx = 0, len = commands.length; idx < len; idx++) { 47107 this[commands[idx]] = (function (sCmd) { 47108 return function (value) { 47109 _this.beforeCommand(); 47110 document.execCommand(sCmd, false, value); 47111 _this.afterCommand(true); 47112 }; 47113 })(commands[idx]); 47114 this.context.memo('help.' + commands[idx], this.lang.help[commands[idx]]); 47115 } 47116 this.fontName = this.wrapCommand(function (value) { 47117 return _this.fontStyling('font-family', "\'" + value + "\'"); 47118 }); 47119 this.fontSize = this.wrapCommand(function (value) { 47120 return _this.fontStyling('font-size', value + 'px'); 47121 }); 47122 for (var idx = 1; idx <= 6; idx++) { 47123 this['formatH' + idx] = (function (idx) { 47124 return function () { 47125 _this.formatBlock('H' + idx); 47126 }; 47127 })(idx); 47128 this.context.memo('help.formatH' + idx, this.lang.help['formatH' + idx]); 47129 } 47130 this.insertParagraph = this.wrapCommand(function () { 47131 _this.typing.insertParagraph(_this.editable); 47132 }); 47133 this.insertOrderedList = this.wrapCommand(function () { 47134 _this.bullet.insertOrderedList(_this.editable); 47135 }); 47136 this.insertUnorderedList = this.wrapCommand(function () { 47137 _this.bullet.insertUnorderedList(_this.editable); 47138 }); 47139 this.indent = this.wrapCommand(function () { 47140 _this.bullet.indent(_this.editable); 47141 }); 47142 this.outdent = this.wrapCommand(function () { 47143 _this.bullet.outdent(_this.editable); 47144 }); 47145 /**
vendor: 3,599 bytes, lines 47146-47240
47146 * insertNode 47147 * insert node 47148 * @param {Node} node 47149 */ 47150 this.insertNode = this.wrapCommand(function (node) { 47151 if (_this.isLimited($$1(node).text().length)) { 47152 return; 47153 } 47154 var rng = _this.getLastRange(); 47155 rng.insertNode(node); 47156 range.createFromNodeAfter(node).select(); 47157 _this.setLastRange(); 47158 }); 47159 /** 47160 * insert text 47161 * @param {String} text 47162 */ 47163 this.insertText = this.wrapCommand(function (text) { 47164 if (_this.isLimited(text.length)) { 47165 return; 47166 } 47167 var rng = _this.getLastRange(); 47168 var textNode = rng.insertNode(dom.createText(text)); 47169 range.create(textNode, dom.nodeLength(textNode)).select(); 47170 _this.setLastRange(); 47171 }); 47172 /** 47173 * paste HTML 47174 * @param {String} markup 47175 */ 47176 this.pasteHTML = this.wrapCommand(function (markup) { 47177 if (_this.isLimited(markup.length)) { 47178 return; 47179 } 47180 markup = _this.context.invoke('codeview.purify', markup); 47181 var contents = _this.getLastRange().pasteHTML(markup); 47182 range.createFromNodeAfter(lists.last(contents)).select(); 47183 _this.setLastRange(); 47184 }); 47185 /** 47186 * formatBlock 47187 * 47188 * @param {String} tagName 47189 */ 47190 this.formatBlock = this.wrapCommand(function (tagName, $target) { 47191 var onApplyCustomStyle = _this.options.callbacks.onApplyCustomStyle; 47192 if (onApplyCustomStyle) { 47193 onApplyCustomStyle.call(_this, $target, _this.context, _this.onFormatBlock); 47194 } 47195 else { 47196 _this.onFormatBlock(tagName, $target); 47197 } 47198 }); 47199 /** 47200 * insert horizontal rule 47201 */ 47202 this.insertHorizontalRule = this.wrapCommand(function () { 47203 var hrNode = _this.getLastRange().insertNode(dom.create('HR')); 47204 if (hrNode.nextSibling) { 47205 range.create(hrNode.nextSibling, 0).normalize().select(); 47206 _this.setLastRange(); 47207 } 47208 }); 47209 /** 47210 * lineHeight 47211 * @param {String} value 47212 */ 47213 this.lineHeight = this.wrapCommand(function (value) { 47214 _this.style.stylePara(_this.getLastRange(), { 47215 lineHeight: value 47216 }); 47217 }); 47218 /** 47219 * create link (command) 47220 * 47221 * @param {Object} linkInfo 47222 */ 47223 this.createLink = this.wrapCommand(function (linkInfo) { 47224 var linkUrl = linkInfo.url; 47225 var linkText = linkInfo.text; 47226 var isNewWindow = linkInfo.isNewWindow; 47227 var rng = linkInfo.range || _this.getLastRange(); 47228 var additionalTextLength = linkText.length - rng.toString().length; 47229 if (additionalTextLength > 0 && _this.isLimited(additionalTextLength)) { 47230 return; 47231 } 47232 var isTextChanged = rng.toString() !== linkText; 47233 // handle spaced urls from input 47234 if (typeof linkUrl === 'string') { 47235 linkUrl = linkUrl.trim(); 47236 } 47237 if (_this.options.onCreateLink) { 47238 linkUrl = _this.options.onCreateLink(linkUrl); 47239 } 47240 else {
47241 // if url doesn't have any protocol and not even a relative or a label, use http:// as default 47242 linkUrl = /^([A-Za-z][A-Za-z0-9+-.]*\:|#|\/)/.test(linkUrl) 47243 ? linkUrl : 'http://' + linkUrl; 47244 } 47245 var anchors = []; 47246 if (isTextChanged) { 47247 rng = rng.deleteContents(); 47248 var anchor = rng.insertNode($$1('<A>' + linkText + '</A>')[0]); 47249 anchors.push(anchor); 47250 } 47251 else { 47252 anchors = _this.style.styleNodes(rng, { 47253 nodeName: 'A', 47254 expandClosestSibling: true, 47255 onlyPartialContains: true 47256 }); 47257 } 47258 $$1.each(anchors, function (idx, anchor) { 47259 $$1(anchor).attr('href', linkUrl); 47260 if (isNewWindow) { 47261 $$1(anchor).attr('target', '_blank'); 47262 } 47263 else { 47264 $$1(anchor).removeAttr('target'); 47265 } 47266 }); 47267 var startRange = range.createFromNodeBefore(lists.head(anchors)); 47268 var startPoint = startRange.getStartPoint(); 47269 var endRange = range.createFromNodeAfter(lists.last(anchors)); 47270 var endPoint = endRange.getEndPoint(); 47271 range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset).select(); 47272 _this.setLastRange(); 47273 }); 47274 /** 47275 * setting color 47276 * 47277 * @param {Object} sObjColor color code 47278 * @param {String} sObjColor.foreColor foreground color 47279 * @param {String} sObjColor.backColor background color 47280 */ 47281 this.color = this.wrapCommand(function (colorInfo) { 47282 var foreColor = colorInfo.foreColor; 47283 var backColor = colorInfo.backColor; 47284 if (foreColor) { 47285 document.execCommand('foreColor', false, foreColor); 47286 } 47287 if (backColor) { 47288 document.execCommand('backColor', false, backColor); 47289 } 47290 }); 47291 /** 47292 * Set foreground color 47293 * 47294 * @param {String} colorCode foreground color code 47295 */ 47296 this.foreColor = this.wrapCommand(function (colorInfo) { 47297 document.execCommand('styleWithCSS', false, true); 47298 document.execCommand('foreColor', false, colorInfo); 47299 }); 47300 /** 47301 * insert Table 47302 * 47303 * @param {String} dimension of table (ex : "5x5") 47304 */ 47305 this.insertTable = this.wrapCommand(function (dim) { 47306 var dimension = dim.split('x'); 47307 var rng = _this.getLastRange().deleteContents(); 47308 rng.insertNode(_this.table.createTable(dimension[0], dimension[1], _this.options)); 47309 }); 47310 /** 47311 * remove media object and Figure Elements if media object is img with Figure. 47312 */ 47313 this.removeMedia = this.wrapCommand(function () { 47314 var $target = $$1(_this.restoreTarget()).parent(); 47315 if ($target.parent('figure').length) { 47316 $target.parent('figure').remove(); 47317 } 47318 else { 47319 $target = $$1(_this.restoreTarget()).detach(); 47320 } 47321 _this.context.triggerEvent('media.delete', $target, _this.$editable); 47322 }); 47323 /** 47324 * float me 47325 * 47326 * @param {String} value 47327 */ 47328 this.floatMe = this.wrapCommand(function (value) { 47329 var $target = $$1(_this.restoreTarget()); 47330 $target.toggleClass('note-float-left', value === 'left'); 47331 $target.toggleClass('note-float-right', value === 'right'); 47332 $target.css('float', (value === 'none' ? '' : value)); 47333 }); 47334 /** 47335 * resize overlay element 47336 * @param {String} value 47337 */ 47338 this.resize = this.wrapCommand(function (value) { 47339 var $target = $$1(_this.restoreTarget()); 47340 value = parseFloat(value); 47341 if (value === 0) { 47342 $target.css('width', ''); 47343 } 47344 else { 47345 $target.css({ 47346 width: value * 100 + '%', 47347 height: '' 47348 }); 47349 } 47350 }); 47351 } 47352 Editor.prototype.initialize = function () { 47353 var _this = this; 47354 // bind custom events 47355 this.$editable.on('keydown', function (event) { 47356 if (event.keyCode === key.code.ENTER) { 47357 _this.context.triggerEvent('enter', event); 47358 } 47359 _this.context.triggerEvent('keydown', event); 47360 if (!event.isDefaultPrevented()) { 47361 if (_this.options.shortcuts) { 47362 _this.handleKeyMap(event); 47363 } 47364 else { 47365 _this.preventDefaultEditableShortCuts(event); 47366 } 47367 } 47368 if (_this.isLimited(1, event)) { 47369 return false;
47370 } 47371 }).on('keyup', function (event) { 47372 _this.setLastRange(); 47373 _this.context.triggerEvent('keyup', event); 47374 }).on('focus', function (event) { 47375 _this.setLastRange(); 47376 _this.context.triggerEvent('focus', event); 47377 }).on('blur', function (event) { 47378 _this.context.triggerEvent('blur', event); 47379 }).on('mousedown', function (event) { 47380 _this.context.triggerEvent('mousedown', event); 47381 }).on('mouseup', function (event) { 47382 _this.setLastRange(); 47383 _this.context.triggerEvent('mouseup', event); 47384 }).on('scroll', function (event) { 47385 _this.context.triggerEvent('scroll', event); 47386 }).on('paste', function (event) { 47387 _this.setLastRange(); 47388 _this.context.triggerEvent('paste', event); 47389 }); 47390 this.$editable.attr('spellcheck', this.options.spellCheck); 47391 // init content before set event 47392 this.$editable.html(dom.html(this.$note) || dom.emptyPara); 47393 this.$editable.on(env.inputEventName, func.debounce(function () { 47394 _this.context.triggerEvent('change', _this.$editable.html(), _this.$editable); 47395 }, 10)); 47396 this.$editor.on('focusin', function (event) { 47397 _this.context.triggerEvent('focusin', event); 47398 }).on('focusout', function (event) { 47399 _this.context.triggerEvent('focusout', event); 47400 }); 47401 if (!this.options.airMode) { 47402 if (this.options.width) { 47403 this.$editor.outerWidth(this.options.width); 47404 } 47405 if (this.options.height) { 47406 this.$editable.outerHeight(this.options.height); 47407 } 47408 if (this.options.maxHeight) { 47409 this.$editable.css('max-height', this.options.maxHeight); 47410 } 47411 if (this.options.minHeight) { 47412 this.$editable.css('min-height', this.options.minHeight); 47413 } 47414 } 47415 this.history.recordUndo(); 47416 this.setLastRange(); 47417 }; 47418 Editor.prototype.destroy = function () { 47419 this.$editable.off(); 47420 }; 47421 Editor.prototype.handleKeyMap = function (event) { 47422 var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc']; 47423 var keys = []; 47424 if (event.metaKey) { 47425 keys.push('CMD'); 47426 } 47427 if (event.ctrlKey && !event.altKey) { 47428 keys.push('CTRL'); 47429 } 47430 if (event.shiftKey) { 47431 keys.push('SHIFT'); 47432 } 47433 var keyName = key.nameFromCode[event.keyCode]; 47434 if (keyName) { 47435 keys.push(keyName); 47436 } 47437 var eventName = keyMap[keys.join('+')]; 47438 if (eventName) { 47439 if (this.context.invoke(eventName) !== false) { 47440 event.preventDefault(); 47441 } 47442 } 47443 else if (key.isEdit(event.keyCode)) { 47444 this.afterCommand(); 47445 } 47446 }; 47447 Editor.prototype.preventDefaultEditableShortCuts = function (event) { 47448 // B(Bold, 66) / I(Italic, 73) / U(Underline, 85) 47449 if ((event.ctrlKey || event.metaKey) && 47450 lists.contains([66, 73, 85], event.keyCode)) { 47451 event.preventDefault(); 47452 } 47453 }; 47454 Editor.prototype.isLimited = function (pad, event) { 47455 pad = pad || 0; 47456 if (typeof event !== 'undefined') { 47457 if (key.isMove(event.keyCode) || 47458 (event.ctrlKey || event.metaKey) || 47459 lists.contains([key.code.BACKSPACE, key.code.DELETE], event.keyCode)) { 47460 return false; 47461 } 47462 } 47463 if (this.options.maxTextLength > 0) { 47464 if ((this.$editable.text().length + pad) >= this.options.maxTextLength) { 47465 return true; 47466 } 47467 } 47468 return false; 47469 }; 47470 /** 47471 * create range 47472 * @return {WrappedRange} 47473 */ 47474 Editor.prototype.createRange = function () { 47475 this.focus(); 47476 this.setLastRange(); 47477 return this.getLastRange(); 47478 }; 47479 Editor.prototype.setLastRange = function () { 47480 this.lastRange = range.create(this.editable); 47481 }; 47482 Editor.prototype.getLastRange = function () { 47483 if (!this.lastRange) { 47484 this.setLastRange(); 47485 } 47486 return this.lastRange; 47487 }; 47488 /** 47489 * saveRange 47490 * 47491 * save current range 47492 * 47493 * @param {Boolean} [thenCollapse=false] 47494 */ 47495 Editor.prototype.saveRange = function (thenCollapse) { 47496 if (thenCollapse) { 47497 this.getLastRange().collapse().select(); 47498 } 47499 }; 47500 /** 47501 * restoreRange 47502 * 47503 * restore lately range 47504 */ 47505 Editor.prototype.restoreRange = function () { 47506 if (this.lastRange) { 47507 this.lastRange.select(); 47508 this.focus(); 47509 } 47510 }; 47511 Editor.prototype.saveTarget = function (node) { 47512 this.$editable.data('target', node); 47513 }; 47514 Editor.prototype.clearTarget = function () { 47515 this.$editable.removeData('target'); 47516 }; 47517 Editor.prototype.restoreTarget = function () { 47518 return this.$editable.data('target'); 47519 }; 47520 /** 47521 * currentStyle 47522 * 47523 * current style 47524 * @return {Object|Boolean} unfocus 47525 */ 47526 Editor.prototype.currentStyle = function () { 47527 var rng = range.create(); 47528 if (rng) { 47529 rng = rng.normalize(); 47530 } 47531 return rng ? this.style.current(rng) : this.style.fromNode(this.$editable); 47532 }; 47533 /** 47534 * style from node 47535 * 47536 * @param {jQuery} $node 47537 * @return {Object} 47538 */ 47539 Editor.prototype.styleFromNode = function ($node) { 47540 return this.style.fromNode($node); 47541 }; 47542 /** 47543 * undo 47544 */ 47545 Editor.prototype.undo = function () { 47546 this.context.triggerEvent('before.command', this.$editable.html()); 47547 this.history.undo(); 47548 this.context.triggerEvent('change', this.$editable.html(), this.$editable); 47549 }; 47550 /* 47551 * commit 47552 */ 47553 Editor.prototype.commit = function () { 47554 this.context.triggerEvent('before.command', this.$editable.html()); 47555 this.history.commit(); 47556 this.context.triggerEvent('change', this.$editable.html(), this.$editable); 47557 }; 47558 /** 47559 * redo 47560 */ 47561 Editor.prototype.redo = function () { 47562 this.context.triggerEvent('before.command', this.$editable.html()); 47563 this.history.redo(); 47564 this.context.triggerEvent('change', this.$editable.html(), this.$editable); 47565 }; 47566 /** 47567 * before command 47568 */ 47569 Editor.prototype.beforeCommand = function () { 47570 this.context.triggerEvent('before.command', this.$editable.html()); 47571 // keep focus on editable before command execution 47572 this.focus(); 47573 }; 47574 /** 47575 * after command 47576 * @param {Boolean} isPreventTrigger 47577 */ 47578 Editor.prototype.afterCommand = function (isPreventTrigger) { 47579 this.normalizeContent(); 47580 this.history.recordUndo(); 47581 if (!isPreventTrigger) { 47582 this.context.triggerEvent('change', this.$editable.html(), this.$editable); 47583 } 47584 }; 47585 /** 47586 * handle tab key 47587 */ 47588 Editor.prototype.tab = function () { 47589 var rng = this.getLastRange(); 47590 if (rng.isCollapsed() && rng.isOnCell()) { 47591 this.table.tab(rng); 47592 } 47593 else { 47594 if (this.options.tabSize === 0) { 47595 return false;
vendor: 6,446 bytes, lines 47596-47772
47596 } 47597 if (!this.isLimited(this.options.tabSize)) { 47598 this.beforeCommand(); 47599 this.typing.insertTab(rng, this.options.tabSize); 47600 this.afterCommand(); 47601 } 47602 } 47603 }; 47604 /** 47605 * handle shift+tab key 47606 */ 47607 Editor.prototype.untab = function () { 47608 var rng = this.getLastRange(); 47609 if (rng.isCollapsed() && rng.isOnCell()) { 47610 this.table.tab(rng, true); 47611 } 47612 else { 47613 if (this.options.tabSize === 0) { 47614 return false; 47615 } 47616 } 47617 }; 47618 /** 47619 * run given function between beforeCommand and afterCommand 47620 */ 47621 Editor.prototype.wrapCommand = function (fn) { 47622 return function () { 47623 this.beforeCommand(); 47624 fn.apply(this, arguments); 47625 this.afterCommand(); 47626 }; 47627 }; 47628 /** 47629 * insert image 47630 * 47631 * @param {String} src 47632 * @param {String|Function} param 47633 * @return {Promise} 47634 */ 47635 Editor.prototype.insertImage = function (src, param) { 47636 var _this = this; 47637 return createImage(src, param).then(function ($image) { 47638 _this.beforeCommand(); 47639 if (typeof param === 'function') { 47640 param($image); 47641 } 47642 else { 47643 if (typeof param === 'string') { 47644 $image.attr('data-filename', param); 47645 } 47646 $image.css('width', Math.min(_this.$editable.width(), $image.width())); 47647 } 47648 $image.show(); 47649 range.create(_this.editable).insertNode($image[0]); 47650 range.createFromNodeAfter($image[0]).select(); 47651 _this.setLastRange(); 47652 _this.afterCommand(); 47653 }).fail(function (e) { 47654 _this.context.triggerEvent('image.upload.error', e); 47655 }); 47656 }; 47657 /** 47658 * insertImages 47659 * @param {File[]} files 47660 */ 47661 Editor.prototype.insertImagesAsDataURL = function (files) { 47662 var _this = this; 47663 $$1.each(files, function (idx, file) { 47664 var filename = file.name; 47665 if (_this.options.maximumImageFileSize && _this.options.maximumImageFileSize < file.size) { 47666 _this.context.triggerEvent('image.upload.error', _this.lang.image.maximumFileSizeError); 47667 } 47668 else { 47669 readFileAsDataURL(file).then(function (dataURL) { 47670 return _this.insertImage(dataURL, filename); 47671 }).fail(function () { 47672 _this.context.triggerEvent('image.upload.error'); 47673 }); 47674 } 47675 }); 47676 }; 47677 /** 47678 * insertImagesOrCallback 47679 * @param {File[]} files 47680 */ 47681 Editor.prototype.insertImagesOrCallback = function (files) { 47682 var callbacks = this.options.callbacks; 47683 // If onImageUpload set, 47684 if (callbacks.onImageUpload) { 47685 this.context.triggerEvent('image.upload', files); 47686 // else insert Image as dataURL 47687 } 47688 else { 47689 this.insertImagesAsDataURL(files); 47690 } 47691 }; 47692 /** 47693 * return selected plain text 47694 * @return {String} text 47695 */ 47696 Editor.prototype.getSelectedText = function () { 47697 var rng = this.getLastRange(); 47698 // if range on anchor, expand range with anchor 47699 if (rng.isOnAnchor()) { 47700 rng = range.createFromNode(dom.ancestor(rng.sc, dom.isAnchor)); 47701 } 47702 return rng.toString(); 47703 }; 47704 Editor.prototype.onFormatBlock = function (tagName, $target) { 47705 // [workaround] for MSIE, IE need `<` 47706 document.execCommand('FormatBlock', false, env.isMSIE ? '<' + tagName + '>' : tagName); 47707 // support custom class 47708 if ($target && $target.length) { 47709 // find the exact element has given tagName 47710 if ($target[0].tagName.toUpperCase() !== tagName.toUpperCase()) { 47711 $target = $target.find(tagName); 47712 } 47713 if ($target && $target.length) { 47714 var className = $target[0].className || ''; 47715 if (className) { 47716 var currentRange = this.createRange(); 47717 var $parent = $$1([currentRange.sc, currentRange.ec]).closest(tagName); 47718 $parent.addClass(className); 47719 } 47720 } 47721 } 47722 }; 47723 Editor.prototype.formatPara = function () { 47724 this.formatBlock('P'); 47725 }; 47726 Editor.prototype.fontStyling = function (target, value) { 47727 var rng = this.getLastRange(); 47728 if (rng) { 47729 var spans = this.style.styleNodes(rng); 47730 $$1(spans).css(target, value); 47731 // [workaround] added styled bogus span for style 47732 // - also bogus character needed for cursor position 47733 if (rng.isCollapsed()) { 47734 var firstSpan = lists.head(spans); 47735 if (firstSpan && !dom.nodeLength(firstSpan)) { 47736 firstSpan.innerHTML = dom.ZERO_WIDTH_NBSP_CHAR; 47737 range.createFromNodeAfter(firstSpan.firstChild).select(); 47738 this.setLastRange(); 47739 this.$editable.data(KEY_BOGUS, firstSpan); 47740 } 47741 } 47742 } 47743 }; 47744 /** 47745 * unlink 47746 * 47747 * @type command 47748 */ 47749 Editor.prototype.unlink = function () { 47750 var rng = this.getLastRange(); 47751 if (rng.isOnAnchor()) { 47752 var anchor = dom.ancestor(rng.sc, dom.isAnchor); 47753 rng = range.createFromNode(anchor); 47754 rng.select(); 47755 this.setLastRange(); 47756 this.beforeCommand(); 47757 document.execCommand('unlink'); 47758 this.afterCommand(); 47759 } 47760 }; 47761 /** 47762 * returns link info 47763 * 47764 * @return {Object} 47765 * @return {WrappedRange} return.range 47766 * @return {String} return.text 47767 * @return {Boolean} [return.isNewWindow=true] 47768 * @return {String} [return.url=""] 47769 */ 47770 Editor.prototype.getLinkInfo = function () { 47771 var rng = this.getLastRange().expand(dom.isAnchor); 47772 // Get the first anchor on range(for edit).
47773 var $anchor = $$1(lists.head(rng.nodes(dom.isAnchor))); 47774 var linkInfo = { 47775 range: rng, 47776 text: rng.toString(), 47777 url: $anchor.length ? $anchor.attr('href') : '' 47778 }; 47779 // When anchor exists, 47780 if ($anchor.length) { 47781 // Set isNewWindow by checking its target. 47782 linkInfo.isNewWindow = $anchor.attr('target') === '_blank'; 47783 } 47784 return linkInfo; 47785 }; 47786 Editor.prototype.addRow = function (position) { 47787 var rng = this.getLastRange(this.$editable); 47788 if (rng.isCollapsed() && rng.isOnCell()) { 47789 this.beforeCommand(); 47790 this.table.addRow(rng, position); 47791 this.afterCommand(); 47792 } 47793 }; 47794 Editor.prototype.addCol = function (position) { 47795 var rng = this.getLastRange(this.$editable); 47796 if (rng.isCollapsed() && rng.isOnCell()) { 47797 this.beforeCommand(); 47798 this.table.addCol(rng, position); 47799 this.afterCommand(); 47800 } 47801 }; 47802 Editor.prototype.deleteRow = function () { 47803 var rng = this.getLastRange(this.$editable); 47804 if (rng.isCollapsed() && rng.isOnCell()) { 47805 this.beforeCommand(); 47806 this.table.deleteRow(rng); 47807 this.afterCommand(); 47808 } 47809 }; 47810 Editor.prototype.deleteCol = function () { 47811 var rng = this.getLastRange(this.$editable); 47812 if (rng.isCollapsed() && rng.isOnCell()) { 47813 this.beforeCommand(); 47814 this.table.deleteCol(rng); 47815 this.afterCommand(); 47816 } 47817 }; 47818 Editor.prototype.deleteTable = function () { 47819 var rng = this.getLastRange(this.$editable); 47820 if (rng.isCollapsed() && rng.isOnCell()) { 47821 this.beforeCommand(); 47822 this.table.deleteTable(rng); 47823 this.afterCommand(); 47824 } 47825 }; 47826 /** 47827 * @param {Position} pos 47828 * @param {jQuery} $target - target element 47829 * @param {Boolean} [bKeepRatio] - keep ratio 47830 */ 47831 Editor.prototype.resizeTo = function (pos, $target, bKeepRatio) { 47832 var imageSize; 47833 if (bKeepRatio) { 47834 var newRatio = pos.y / pos.x; 47835 var ratio = $target.data('ratio'); 47836 imageSize = { 47837 width: ratio > newRatio ? pos.x : pos.y / ratio, 47838 height: ratio > newRatio ? pos.x * ratio : pos.y 47839 }; 47840 } 47841 else { 47842 imageSize = { 47843 width: pos.x, 47844 height: pos.y 47845 }; 47846 } 47847 $target.css(imageSize); 47848 }; 47849 /** 47850 * returns whether editable area has focus or not. 47851 */ 47852 Editor.prototype.hasFocus = function () { 47853 return this.$editable.is(':focus'); 47854 }; 47855 /** 47856 * set focus 47857 */ 47858 Editor.prototype.focus = function () { 47859 // [workaround] Screen will move when page is scolled in IE. 47860 // - do focus when not focused 47861 if (!this.hasFocus()) { 47862 this.$editable.focus(); 47863 } 47864 }; 47865 /** 47866 * returns whether contents is empty or not. 47867 * @return {Boolean} 47868 */ 47869 Editor.prototype.isEmpty = function () { 47870 return dom.isEmpty(this.$editable[0]) || dom.emptyPara === this.$editable.html(); 47871 }; 47872 /** 47873 * Removes all contents and restores the editable instance to an _emptyPara_. 47874 */ 47875 Editor.prototype.empty = function () { 47876 this.context.invoke('code', dom.emptyPara); 47877 }; 47878 /** 47879 * normalize content 47880 */ 47881 Editor.prototype.normalizeContent = function () { 47882 this.$editable[0].normalize(); 47883 }; 47884 return Editor; 47885 }()); 47886 47887 var Clipboard = /** @class */ (function () { 47888 function Clipboard(context) { 47889 this.context = context; 47890 this.$editable = context.layoutInfo.editable; 47891 } 47892 Clipboard.prototype.initialize = function () { 47893 this.$editable.on('paste', this.pasteByEvent.bind(this)); 47894 }; 47895 /** 47896 * paste by clipboard event 47897 * 47898 * @param {Event} event 47899 */ 47900 Clipboard.prototype.pasteByEvent = function (event) { 47901 var clipboardData = event.originalEvent.clipboardData; 47902 if (clipboardData && clipboardData.items && clipboardData.items.length) { 47903 // paste img file 47904 var item = clipboardData.items.length > 1 ? clipboardData.items[1] : lists.head(clipboardData.items); 47905 if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
47906 this.context.invoke('editor.insertImagesOrCallback', [item.getAsFile()]); 47907 } 47908 this.context.invoke('editor.afterCommand'); 47909 } 47910 }; 47911 return Clipboard; 47912 }()); 47913 47914 var Dropzone = /** @class */ (function () { 47915 function Dropzone(context) { 47916 this.context = context; 47917 this.$eventListener = $$1(document); 47918 this.$editor = context.layoutInfo.editor; 47919 this.$editable = context.layoutInfo.editable; 47920 this.options = context.options; 47921 this.lang = this.options.langInfo; 47922 this.documentEventHandlers = {}; 47923 this.$dropzone = $$1([ 47924 '<div class="note-dropzone">', 47925 ' <div class="note-dropzone-message"/>', 47926 '</div>', 47927 ].join('')).prependTo(this.$editor); 47928 } 47929 /** 47930 * attach Drag and Drop Events 47931 */ 47932 Dropzone.prototype.initialize = function () { 47933 if (this.options.disableDragAndDrop) { 47934 // prevent default drop event 47935 this.documentEventHandlers.onDrop = function (e) { 47936 e.preventDefault(); 47937 }; 47938 // do not consider outside of dropzone 47939 this.$eventListener = this.$dropzone; 47940 this.$eventListener.on('drop', this.documentEventHandlers.onDrop); 47941 } 47942 else { 47943 this.attachDragAndDropEvent(); 47944 } 47945 }; 47946 /** 47947 * attach Drag and Drop Events 47948 */ 47949 Dropzone.prototype.attachDragAndDropEvent = function () { 47950 var _this = this; 47951 var collection = $$1(); 47952 var $dropzoneMessage = this.$dropzone.find('.note-dropzone-message'); 47953 this.documentEventHandlers.onDragenter = function (e) { 47954 var isCodeview = _this.context.invoke('codeview.isActivated'); 47955 var hasEditorSize = _this.$editor.width() > 0 && _this.$editor.height() > 0; 47956 if (!isCodeview && !collection.length && hasEditorSize) { 47957 _this.$editor.addClass('dragover'); 47958 _this.$dropzone.width(_this.$editor.width()); 47959 _this.$dropzone.height(_this.$editor.height()); 47960 $dropzoneMessage.text(_this.lang.image.dragImageHere); 47961 } 47962 collection = collection.add(e.target); 47963 }; 47964 this.documentEventHandlers.onDragleave = function (e) { 47965 collection = collection.not(e.target); 47966 if (!collection.length) { 47967 _this.$editor.removeClass('dragover'); 47968 } 47969 }; 47970 this.documentEventHandlers.onDrop = function () { 47971 collection = $$1(); 47972 _this.$editor.removeClass('dragover'); 47973 }; 47974 // show dropzone on dragenter when dragging a object to document 47975 // -but only if the editor is visible, i.e. has a positive width and height 47976 this.$eventListener.on('dragenter', this.documentEventHandlers.onDragenter) 47977 .on('dragleave', this.documentEventHandlers.onDragleave) 47978 .on('drop', this.documentEventHandlers.onDrop); 47979 // change dropzone's message on hover. 47980 this.$dropzone.on('dragenter', function () { 47981 _this.$dropzone.addClass('hover'); 47982 $dropzoneMessage.text(_this.lang.image.dropImage); 47983 }).on('dragleave', function () { 47984 _this.$dropzone.removeClass('hover'); 47985 $dropzoneMessage.text(_this.lang.image.dragImageHere); 47986 }); 47987 // attach dropImage 47988 this.$dropzone.on('drop', function (event) { 47989 var dataTransfer = event.originalEvent.dataTransfer; 47990 // stop the browser from opening the dropped content 47991 event.preventDefault(); 47992 if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { 47993 _this.$editable.focus(); 47994 _this.context.invoke('editor.insertImagesOrCallback', dataTransfer.files); 47995 } 47996 else { 47997 $$1.each(dataTransfer.types, function (idx, type) { 47998 var content = dataTransfer.getData(type); 47999 if (type.toLowerCase().indexOf('text') > -1) {
48000 _this.context.invoke('editor.pasteHTML', content); 48001 } 48002 else { 48003 $$1(content).each(function (idx, item) { 48004 _this.context.invoke('editor.insertNode', item); 48005 }); 48006 } 48007 }); 48008 } 48009 }).on('dragover', false); // prevent default dragover event 48010 }; 48011 Dropzone.prototype.destroy = function () { 48012 var _this = this; 48013 Object.keys(this.documentEventHandlers).forEach(function (key) { 48014 _this.$eventListener.off(key.substr(2).toLowerCase(), _this.documentEventHandlers[key]); 48015 }); 48016 this.documentEventHandlers = {}; 48017 }; 48018 return Dropzone; 48019 }()); 48020 48021 var CodeMirror; 48022 if (env.hasCodeMirror) { 48023 CodeMirror = window.CodeMirror; 48024 } 48025 /** 48026 * @class Codeview 48027 */ 48028 var CodeView = /** @class */ (function () { 48029 function CodeView(context) { 48030 this.context = context; 48031 this.$editor = context.layoutInfo.editor; 48032 this.$editable = context.layoutInfo.editable; 48033 this.$codable = context.layoutInfo.codable; 48034 this.options = context.options; 48035 } 48036 CodeView.prototype.sync = function () { 48037 var isCodeview = this.isActivated(); 48038 if (isCodeview && env.hasCodeMirror) { 48039 this.$codable.data('cmEditor').save(); 48040 } 48041 }; 48042 /** 48043 * @return {Boolean} 48044 */ 48045 CodeView.prototype.isActivated = function () { 48046 return this.$editor.hasClass('codeview'); 48047 }; 48048 /** 48049 * toggle codeview 48050 */ 48051 CodeView.prototype.toggle = function () { 48052 if (this.isActivated()) { 48053 this.deactivate(); 48054 } 48055 else { 48056 this.activate(); 48057 } 48058 this.context.triggerEvent('codeview.toggled'); 48059 }; 48060 /** 48061 * purify input value 48062 * @param value 48063 * @returns {*} 48064 */ 48065 CodeView.prototype.purify = function (value) { 48066 if (this.options.codeviewFilter) { 48067 // filter code view regex 48068 value = value.replace(this.options.codeviewFilterRegex, ''); 48069 // allow specific iframe tag 48070 if (this.options.codeviewIframeFilter) { 48071 var whitelist_1 = this.options.codeviewIframeWhitelistSrc.concat(this.options.codeviewIframeWhitelistSrcBase); 48072 value = value.replace(/(<iframe.*?>.*?(?:<\/iframe>)?)/gi, function (tag) { 48073 // remove if src attribute is duplicated 48074 if (/<.+src(?==?('|"|\s)?)[\s\S]+src(?=('|"|\s)?)[^>]*?>/i.test(tag)) { 48075 return ''; 48076 } 48077 for (var _i = 0, whitelist_2 = whitelist_1; _i < whitelist_2.length; _i++) { 48078 var src = whitelist_2[_i]; 48079 // pass if src is trusted 48080 if ((new RegExp('src="(https?:)?\/\/' + src.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '\/(.+)"')).test(tag)) { 48081 return tag; 48082 } 48083 } 48084 return ''; 48085 }); 48086 } 48087 } 48088 return value; 48089 }; 48090 /** 48091 * activate code view 48092 */ 48093 CodeView.prototype.activate = function () { 48094 var _this = this; 48095 this.$codable.val(dom.html(this.$editable, this.options.prettifyHtml)); 48096 this.$codable.height(this.$editable.height()); 48097 this.context.invoke('toolbar.updateCodeview', true); 48098 this.$editor.addClass('codeview'); 48099 this.$codable.focus(); 48100 // activate CodeMirror as codable 48101 if (env.hasCodeMirror) { 48102 var cmEditor_1 = CodeMirror.fromTextArea(this.$codable[0], this.options.codemirror); 48103 // CodeMirror TernServer 48104 if (this.options.codemirror.tern) { 48105 var server_1 = new CodeMirror.TernServer(this.options.codemirror.tern); 48106 cmEditor_1.ternServer = server_1; 48107 cmEditor_1.on('cursorActivity', function (cm) { 48108 server_1.updateArgHints(cm); 48109 }); 48110 } 48111 cmEditor_1.on('blur', function (event) { 48112 _this.context.triggerEvent('blur.codeview', cmEditor_1.getValue(), event); 48113 }); 48114 cmEditor_1.on('change', function (event) { 48115 _this.context.triggerEvent('change.codeview', cmEditor_1.getValue(), cmEditor_1); 48116 }); 48117 // CodeMirror hasn't Padding. 48118 cmEditor_1.setSize(null, this.$editable.outerHeight()); 48119 this.$codable.data('cmEditor', cmEditor_1); 48120 } 48121 else { 48122 this.$codable.on('blur', function (event) { 48123 _this.context.triggerEvent('blur.codeview', _this.$codable.val(), event); 48124 }); 48125 this.$codable.on('input', function (event) { 48126 _this.context.triggerEvent('change.codeview', _this.$codable.val(), _this.$codable); 48127 }); 48128 } 48129 }; 48130 /** 48131 * deactivate code view 48132 */ 48133 CodeView.prototype.deactivate = function () { 48134 // deactivate CodeMirror as codable 48135 if (env.hasCodeMirror) { 48136 var cmEditor = this.$codable.data('cmEditor'); 48137 this.$codable.val(cmEditor.getValue()); 48138 cmEditor.toTextArea(); 48139 } 48140 var value = this.purify(dom.value(this.$codable, this.options.prettifyHtml) || dom.emptyPara); 48141 var isChange = this.$editable.html() !== value; 48142 this.$editable.html(value); 48143 this.$editable.height(this.options.height ? this.$codable.height() : 'auto'); 48144 this.$editor.removeClass('codeview'); 48145 if (isChange) { 48146 this.context.triggerEvent('change', this.$editable.html(), this.$editable); 48147 } 48148 this.$editable.focus();
48149 this.context.invoke('toolbar.updateCodeview', false); 48150 }; 48151 CodeView.prototype.destroy = function () { 48152 if (this.isActivated()) { 48153 this.deactivate(); 48154 } 48155 }; 48156 return CodeView; 48157 }()); 48158 48159 var EDITABLE_PADDING = 24; 48160 var Statusbar = /** @class */ (function () { 48161 function Statusbar(context) { 48162 this.$document = $$1(document); 48163 this.$statusbar = context.layoutInfo.statusbar; 48164 this.$editable = context.layoutInfo.editable; 48165 this.options = context.options; 48166 } 48167 Statusbar.prototype.initialize = function () { 48168 var _this = this; 48169 if (this.options.airMode || this.options.disableResizeEditor) { 48170 this.destroy(); 48171 return; 48172 } 48173 this.$statusbar.on('mousedown', function (event) { 48174 event.preventDefault(); 48175 event.stopPropagation(); 48176 var editableTop = _this.$editable.offset().top - _this.$document.scrollTop(); 48177 var onMouseMove = function (event) { 48178 var height = event.clientY - (editableTop + EDITABLE_PADDING); 48179 height = (_this.options.minheight > 0) ? Math.max(height, _this.options.minheight) : height; 48180 height = (_this.options.maxHeight > 0) ? Math.min(height, _this.options.maxHeight) : height; 48181 _this.$editable.height(height); 48182 }; 48183 _this.$document.on('mousemove', onMouseMove).one('mouseup', function () { 48184 _this.$document.off('mousemove', onMouseMove); 48185 }); 48186 }); 48187 48188 this.$statusbar.on('touchstart', function (event) { 48189 event.stopPropagation(); 48190 var editableTop = _this.$editable.offset().top - _this.$document.scrollTop(); 48191 var onTouchMove = function (event) { 48192 var height = event.touches[0].clientY - (editableTop + EDITABLE_PADDING); 48193 height = (_this.options.minheight > 0) ? Math.max(height, _this.options.minheight) : height; 48194 height = (_this.options.maxHeight > 0) ? Math.min(height, _this.options.maxHeight) : height; 48195 _this.$editable.height(height); 48196 }; 48197 _this.$document.on('touchmove', onTouchMove).one('touchend', function () { 48198 _this.$document.off('touchmove', onTouchMove); 48199 }); 48200 }); 48201 }; 48202 Statusbar.prototype.destroy = function () { 48203 this.$statusbar.off(); 48204 this.$statusbar.addClass('locked'); 48205 }; 48206 return Statusbar; 48207 }()); 48208 48209 var Fullscreen = /** @class */ (function () { 48210 function Fullscreen(context) { 48211 var _this = this; 48212 this.context = context; 48213 this.$editor = context.layoutInfo.editor; 48214 this.$toolbar = context.layoutInfo.toolbar; 48215 this.$editable = context.layoutInfo.editable; 48216 this.$codable = context.layoutInfo.codable; 48217 this.$window = $$1(window); 48218 this.$scrollbar = $$1('html, body'); 48219 this.onResize = function () { 48220 _this.resizeTo({ 48221 h: _this.$window.height() - _this.$toolbar.outerHeight() 48222 }); 48223 }; 48224 } 48225 Fullscreen.prototype.resizeTo = function (size) { 48226 this.$editable.css('height', size.h); 48227 this.$codable.css('height', size.h); 48228 if (this.$codable.data('cmeditor')) { 48229 this.$codable.data('cmeditor').setsize(null, size.h); 48230 } 48231 }; 48232 /** 48233 * toggle fullscreen 48234 */ 48235 Fullscreen.prototype.toggle = function () { 48236 this.$editor.toggleClass('fullscreen'); 48237 if (this.isFullscreen()) { 48238 this.$editable.data('orgHeight', this.$editable.css('height')); 48239 this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight')); 48240 this.$editable.css('maxHeight', ''); 48241 this.$window.on('resize', this.onResize).trigger('resize'); 48242 this.$scrollbar.css('overflow', 'hidden'); 48243 } 48244 else { 48245 this.$window.off('resize', this.onResize);
48246 this.resizeTo({ h: this.$editable.data('orgHeight') }); 48247 this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight')); 48248 this.$scrollbar.css('overflow', 'visible'); 48249 } 48250 this.context.invoke('toolbar.updateFullscreen', this.isFullscreen()); 48251 }; 48252 Fullscreen.prototype.isFullscreen = function () { 48253 return this.$editor.hasClass('fullscreen'); 48254 }; 48255 return Fullscreen; 48256 }()); 48257 48258 var Handle = /** @class */ (function () { 48259 function Handle(context) { 48260 var _this = this; 48261 this.context = context; 48262 this.$document = $$1(document); 48263 this.$editingArea = context.layoutInfo.editingArea; 48264 this.options = context.options; 48265 this.lang = this.options.langInfo; 48266 this.events = { 48267 'summernote.mousedown': function (we, e) { 48268 if (_this.update(e.target, e)) { 48269 e.preventDefault(); 48270 } 48271 }, 48272 'summernote.keyup summernote.scroll summernote.change summernote.dialog.shown': function () { 48273 _this.update(); 48274 }, 48275 'summernote.disable': function () { 48276 _this.hide(); 48277 }, 48278 'summernote.codeview.toggled': function () { 48279 _this.update(); 48280 } 48281 }; 48282 } 48283 Handle.prototype.initialize = function () { 48284 var _this = this; 48285 this.$handle = $$1([ 48286 '<div class="note-handle">', 48287 '<div class="note-control-selection">', 48288 '<div class="note-control-selection-bg"></div>', 48289 '<div class="note-control-holder note-control-nw"></div>', 48290 '<div class="note-control-holder note-control-ne"></div>', 48291 '<div class="note-control-holder note-control-sw"></div>', 48292 '<div class="', 48293 (this.options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing'), 48294 ' note-control-se"></div>', 48295 (this.options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>'), 48296 '</div>', 48297 '</div>', 48298 ].join('')).prependTo(this.$editingArea); 48299 this.$handle.on('mousedown', function (event) { 48300 if (dom.isControlSizing(event.target)) { 48301 event.preventDefault(); 48302 event.stopPropagation(); 48303 var $target_1 = _this.$handle.find('.note-control-selection').data('target'); 48304 var posStart_1 = $target_1.offset(); 48305 var scrollTop_1 = _this.$document.scrollTop(); 48306 var onMouseMove_1 = function (event) { 48307 _this.context.invoke('editor.resizeTo', { 48308 x: event.clientX - posStart_1.left, 48309 y: event.clientY - (posStart_1.top - scrollTop_1) 48310 }, $target_1, !event.shiftKey); 48311 _this.update($target_1[0], event); 48312 }; 48313 _this.$document 48314 .on('mousemove', onMouseMove_1) 48315 .one('mouseup', function (e) { 48316 e.preventDefault(); 48317 _this.$document.off('mousemove', onMouseMove_1); 48318 _this.context.invoke('editor.afterCommand'); 48319 }); 48320 if (!$target_1.data('ratio')) { // original ratio. 48321 $target_1.data('ratio', $target_1.height() / $target_1.width()); 48322 } 48323 } 48324 }); 48325 48326 this.$handle.on('touchstart', function (event) { 48327 if (dom.isControlSizing(event.target)) { 48328 event.preventDefault(); 48329 event.stopPropagation(); 48330 48331 var $target = _this.$handle.find('.note-control-selection').data('target'), 48332 posStart = $target.offset(), 48333 scrollTop = _this.$document.scrollTop(); 48334 48335 _this.$document.on('touchmove', function (event) {
48336 _this.context.invoke('editor.resizeTo', { 48337 x: event.touches[0].clientX - posStart.left, 48338 y: event.touches[0].clientY - (posStart.top - scrollTop) 48339 }, $target, !event.shiftKey); 48340 48341 _this.update($target[0], event); 48342 }).one('touchend', function (e) { 48343 e.preventDefault(); 48344 _this.$document.off('touchmove'); 48345 _this.context.invoke('editor.afterCommand'); 48346 }); 48347 48348 if (!$target.data('ratio')) { // original ratio. 48349 $target.data('ratio', $target.height() / $target.width()); 48350 } 48351 } 48352 }); 48353 // Listen for scrolling on the handle overlay. 48354 this.$handle.on('wheel', function (e) { 48355 e.preventDefault(); 48356 _this.update(); 48357 }); 48358 }; 48359 Handle.prototype.destroy = function () { 48360 this.$handle.remove(); 48361 }; 48362 Handle.prototype.update = function (target, event) { 48363 if (this.context.isDisabled()) { 48364 return false; 48365 } 48366 var isImage = dom.isImg(target); 48367 var $selection = this.$handle.find('.note-control-selection'); 48368 this.context.invoke('imagePopover.update', target, event); 48369 if (isImage) { 48370 var $image = $$1(target); 48371 var position = $image.position(); 48372 var pos = { 48373 left: position.left + parseInt($image.css('marginLeft'), 10), 48374 top: position.top + parseInt($image.css('marginTop'), 10) 48375 }; 48376 // exclude margin 48377 var imageSize = { 48378 w: $image.outerWidth(false), 48379 h: $image.outerHeight(false) 48380 }; 48381 $selection.css({ 48382 display: 'block', 48383 left: pos.left, 48384 top: pos.top, 48385 width: imageSize.w, 48386 height: imageSize.h 48387 }).data('target', $image); // save current image element. 48388 var origImageObj = new Image(); 48389 origImageObj.src = $image.attr('src'); 48390 var sizingText = imageSize.w + 'x' + imageSize.h + ' (' + this.lang.image.original + ': ' + origImageObj.width + 'x' + origImageObj.height + ')'; 48391 $selection.find('.note-control-selection-info').text(sizingText); 48392 this.context.invoke('editor.saveTarget', target); 48393 } 48394 else { 48395 this.hide(); 48396 } 48397 return isImage; 48398 }; 48399 /** 48400 * hide 48401 * 48402 * @param {jQuery} $handle 48403 */ 48404 Handle.prototype.hide = function () { 48405 this.context.invoke('editor.clearTarget'); 48406 this.$handle.children().hide(); 48407 }; 48408 return Handle; 48409 }()); 48410 48411 var defaultScheme = 'http://'; 48412 var linkPattern = /^([A-Za-z][A-Za-z0-9+-.]*\:[\/]{2}|mailto:[A-Z0-9._%+-]+@)?(www\.)?(.+)$/i; 48413 var AutoLink = /** @class */ (function () { 48414 function AutoLink(context) { 48415 var _this = this; 48416 this.context = context; 48417 this.events = { 48418 'summernote.keyup': function (we, e) { 48419 if (!e.isDefaultPrevented()) { 48420 _this.handleKeyup(e); 48421 } 48422 }, 48423 'summernote.keydown': function (we, e) { 48424 _this.handleKeydown(e); 48425 } 48426 }; 48427 } 48428 AutoLink.prototype.initialize = function () { 48429 this.lastWordRange = null; 48430 }; 48431 AutoLink.prototype.destroy = function () { 48432 this.lastWordRange = null; 48433 }; 48434 AutoLink.prototype.replace = function () { 48435 if (!this.lastWordRange) { 48436 return; 48437 } 48438 var keyword = this.lastWordRange.toString(); 48439 var match = keyword.match(linkPattern); 48440 if (match && (match[1] || match[2])) { 48441 var link = match[1] ? keyword : defaultScheme + keyword; 48442 var node = $$1('<a />').html(keyword).attr('href', link)[0]; 48443 if (this.context.options.linkTargetBlank) { 48444 $$1(node).attr('target', '_blank'); 48445 }
48446 this.lastWordRange.insertNode(node); 48447 this.lastWordRange = null; 48448 this.context.invoke('editor.focus'); 48449 } 48450 }; 48451 AutoLink.prototype.handleKeydown = function (e) { 48452 if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) { 48453 var wordRange = this.context.invoke('editor.createRange').getWordRange(); 48454 this.lastWordRange = wordRange; 48455 } 48456 }; 48457 AutoLink.prototype.handleKeyup = function (e) { 48458 if (lists.contains([key.code.ENTER, key.code.SPACE], e.keyCode)) { 48459 this.replace(); 48460 } 48461 }; 48462 return AutoLink; 48463 }()); 48464 48465 /** 48466 * textarea auto sync. 48467 */ 48468 var AutoSync = /** @class */ (function () { 48469 function AutoSync(context) { 48470 var _this = this; 48471 this.$note = context.layoutInfo.note; 48472 this.events = { 48473 'summernote.change': function () { 48474 _this.$note.val(context.invoke('code')); 48475 } 48476 }; 48477 } 48478 AutoSync.prototype.shouldInitialize = function () { 48479 return dom.isTextarea(this.$note[0]); 48480 }; 48481 return AutoSync; 48482 }()); 48483 48484 var AutoReplace = /** @class */ (function () { 48485 function AutoReplace(context) { 48486 var _this = this; 48487 this.context = context; 48488 this.options = context.options.replace || {}; 48489 this.keys = [key.code.ENTER, key.code.SPACE, key.code.PERIOD, key.code.COMMA, key.code.SEMICOLON, key.code.SLASH]; 48490 this.previousKeydownCode = null; 48491 this.events = { 48492 'summernote.keyup': function (we, e) { 48493 if (!e.isDefaultPrevented()) { 48494 _this.handleKeyup(e); 48495 } 48496 }, 48497 'summernote.keydown': function (we, e) { 48498 _this.handleKeydown(e); 48499 } 48500 }; 48501 } 48502 AutoReplace.prototype.shouldInitialize = function () { 48503 return !!this.options.match; 48504 }; 48505 AutoReplace.prototype.initialize = function () { 48506 this.lastWord = null; 48507 }; 48508 AutoReplace.prototype.destroy = function () { 48509 this.lastWord = null; 48510 }; 48511 AutoReplace.prototype.replace = function () { 48512 if (!this.lastWord) { 48513 return; 48514 } 48515 var self = this; 48516 var keyword = this.lastWord.toString(); 48517 this.options.match(keyword, function (match) { 48518 if (match) { 48519 var node = ''; 48520 if (typeof match === 'string') { 48521 node = dom.createText(match); 48522 } 48523 else if (match instanceof jQuery) { 48524 node = match[0]; 48525 } 48526 else if (match instanceof Node) { 48527 node = match; 48528 } 48529 if (!node) 48530 return; 48531 self.lastWord.insertNode(node); 48532 self.lastWord = null; 48533 self.context.invoke('editor.focus'); 48534 } 48535 }); 48536 }; 48537 AutoReplace.prototype.handleKeydown = function (e) { 48538 // this forces it to remember the last whole word, even if multiple termination keys are pressed 48539 // before the previous key is let go. 48540 if (this.previousKeydownCode && lists.contains(this.keys, this.previousKeydownCode)) { 48541 this.previousKeydownCode = e.keyCode; 48542 return; 48543 } 48544 if (lists.contains(this.keys, e.keyCode)) { 48545 var wordRange = this.context.invoke('editor.createRange').getWordRange(); 48546 this.lastWord = wordRange; 48547 } 48548 this.previousKeydownCode = e.keyCode; 48549 }; 48550 AutoReplace.prototype.handleKeyup = function (e) { 48551 if (lists.contains(this.keys, e.keyCode)) { 48552 this.replace(); 48553 } 48554 }; 48555 return AutoReplace; 48556 }()); 48557 48558 var Placeholder = /** @class */ (function () { 48559 function Placeholder(context) { 48560 var _this = this; 48561 this.context = context; 48562 this.$editingArea = context.layoutInfo.editingArea; 48563 this.options = context.options; 48564 this.events = { 48565 'summernote.init summernote.change': function () { 48566 _this.update(); 48567 }, 48568 'summernote.codeview.toggled': function () { 48569 _this.update(); 48570 } 48571 }; 48572 } 48573 Placeholder.prototype.shouldInitialize = function () { 48574 return !!this.options.placeholder; 48575 }; 48576 Placeholder.prototype.initialize = function () { 48577 var _this = this; 48578 this.$placeholder = $$1('<div class="note-placeholder">'); 48579 this.$placeholder.on('click', function () {
vendor: 11,434 bytes, lines 48580-48786
48580 _this.context.invoke('focus'); 48581 }).html(this.options.placeholder).prependTo(this.$editingArea); 48582 this.update(); 48583 }; 48584 Placeholder.prototype.destroy = function () { 48585 this.$placeholder.remove(); 48586 }; 48587 Placeholder.prototype.update = function () { 48588 var isShow = !this.context.invoke('codeview.isActivated') && this.context.invoke('editor.isEmpty'); 48589 this.$placeholder.toggle(isShow); 48590 }; 48591 return Placeholder; 48592 }()); 48593 48594 var Buttons = /** @class */ (function () { 48595 function Buttons(context) { 48596 this.ui = $$1.summernote.ui; 48597 this.context = context; 48598 this.$toolbar = context.layoutInfo.toolbar; 48599 this.options = context.options; 48600 this.lang = this.options.langInfo; 48601 this.invertedKeyMap = func.invertObject(this.options.keyMap[env.isMac ? 'mac' : 'pc']); 48602 } 48603 Buttons.prototype.representShortcut = function (editorMethod) { 48604 var shortcut = this.invertedKeyMap[editorMethod]; 48605 if (!this.options.shortcuts || !shortcut) { 48606 return ''; 48607 } 48608 if (env.isMac) { 48609 shortcut = shortcut.replace('CMD', 'â').replace('SHIFT', 'â§'); 48610 } 48611 shortcut = shortcut.replace('BACKSLASH', '\\') 48612 .replace('SLASH', '/') 48613 .replace('LEFTBRACKET', '[') 48614 .replace('RIGHTBRACKET', ']'); 48615 return ' (' + shortcut + ')'; 48616 }; 48617 Buttons.prototype.button = function (o) { 48618 if (!this.options.tooltip && o.tooltip) { 48619 delete o.tooltip; 48620 } 48621 o.container = this.options.container; 48622 return this.ui.button(o); 48623 }; 48624 Buttons.prototype.initialize = function () { 48625 this.addToolbarButtons(); 48626 this.addImagePopoverButtons(); 48627 this.addLinkPopoverButtons(); 48628 this.addTablePopoverButtons(); 48629 this.fontInstalledMap = {}; 48630 }; 48631 Buttons.prototype.destroy = function () { 48632 delete this.fontInstalledMap; 48633 }; 48634 Buttons.prototype.isFontInstalled = function (name) { 48635 if (!this.fontInstalledMap.hasOwnProperty(name)) { 48636 this.fontInstalledMap[name] = env.isFontInstalled(name) || 48637 lists.contains(this.options.fontNamesIgnoreCheck, name); 48638 } 48639 return this.fontInstalledMap[name]; 48640 }; 48641 Buttons.prototype.isFontDeservedToAdd = function (name) { 48642 var genericFamilies = ['sans-serif', 'serif', 'monospace', 'cursive', 'fantasy']; 48643 name = name.toLowerCase(); 48644 return (name !== '' && this.isFontInstalled(name) && genericFamilies.indexOf(name) === -1); 48645 }; 48646 Buttons.prototype.colorPalette = function (className, tooltip, backColor, foreColor) { 48647 var _this = this; 48648 return this.ui.buttonGroup({ 48649 className: 'note-color ' + className, 48650 children: [ 48651 this.button({ 48652 className: 'note-current-color-button', 48653 contents: this.ui.icon(this.options.icons.font + ' note-recent-color'), 48654 tooltip: tooltip, 48655 click: function (e) { 48656 var $button = $$1(e.currentTarget); 48657 if (backColor && foreColor) { 48658 _this.context.invoke('editor.color', { 48659 backColor: $button.attr('data-backColor'), 48660 foreColor: $button.attr('data-foreColor') 48661 }); 48662 } 48663 else if (backColor) { 48664 _this.context.invoke('editor.color', { 48665 backColor: $button.attr('data-backColor') 48666 }); 48667 } 48668 else if (foreColor) { 48669 _this.context.invoke('editor.color', { 48670 foreColor: $button.attr('data-foreColor') 48671 }); 48672 } 48673 }, 48674 callback: function ($button) { 48675 var $recentColor = $button.find('.note-recent-color'); 48676 if (backColor) { 48677 $recentColor.css('background-color', _this.options.colorButton.backColor); 48678 $button.attr('data-backColor', _this.options.colorButton.backColor); 48679 } 48680 if (foreColor) { 48681 $recentColor.css('color', _this.options.colorButton.foreColor); 48682 $button.attr('data-foreColor', _this.options.colorButton.foreColor); 48683 } 48684 else { 48685 $recentColor.css('color', 'transparent'); 48686 } 48687 } 48688 }), 48689 this.button({ 48690 className: 'dropdown-toggle', 48691 contents: this.ui.dropdownButtonContents('', this.options), 48692 tooltip: this.lang.color.more, 48693 data: { 48694 toggle: 'dropdown' 48695 } 48696 }), 48697 this.ui.dropdown({ 48698 items: (backColor ? [ 48699 '<div class="note-palette">', 48700 ' <div class="note-palette-title">' + this.lang.color.background + '</div>', 48701 ' <div>', 48702 ' <button type="button" class="note-color-reset btn btn-light" data-event="backColor" data-value="inherit">', 48703 this.lang.color.transparent, 48704 ' </button>', 48705 ' </div>', 48706 ' <div class="note-holder" data-event="backColor"/>', 48707 ' <div>', 48708 ' <button type="button" class="note-color-select btn" data-event="openPalette" data-value="backColorPicker">', 48709 this.lang.color.cpSelect, 48710 ' </button>', 48711 ' <input type="color" id="backColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.backColor + '" data-event="backColorPalette">', 48712 ' </div>', 48713 ' <div class="note-holder-custom" id="backColorPalette" data-event="backColor"/>', 48714 '</div>', 48715 ].join('') : '') + 48716 (foreColor ? [ 48717 '<div class="note-palette">', 48718 ' <div class="note-palette-title">' + this.lang.color.foreground + '</div>', 48719 ' <div>', 48720 ' <button type="button" class="note-color-reset btn btn-light" data-event="removeFormat" data-value="foreColor">', 48721 this.lang.color.resetToDefault, 48722 ' </button>', 48723 ' </div>', 48724 ' <div class="note-holder" data-event="foreColor"/>', 48725 ' <div>', 48726 ' <button type="button" class="note-color-select btn" data-event="openPalette" data-value="foreColorPicker">', 48727 this.lang.color.cpSelect, 48728 ' </button>', 48729 ' <input type="color" id="foreColorPicker" class="note-btn note-color-select-btn" value="' + this.options.colorButton.foreColor + '" data-event="foreColorPalette">', 48730 ' <div class="note-holder-custom" id="foreColorPalette" data-event="foreColor"/>', 48731 '</div>', 48732 ].join('') : ''), 48733 callback: function ($dropdown) { 48734 $dropdown.find('.note-holder').each(function (idx, item) { 48735 var $holder = $$1(item); 48736 $holder.append(_this.ui.palette({ 48737 colors: _this.options.colors, 48738 colorsName: _this.options.colorsName, 48739 eventName: $holder.data('event'), 48740 container: _this.options.container, 48741 tooltip: _this.options.tooltip 48742 }).render()); 48743 }); 48744 /* TODO: do we have to record recent custom colors within cookies? */ 48745 var customColors = [ 48746 ['#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF', '#FFFFFF'], 48747 ]; 48748 $dropdown.find('.note-holder-custom').each(function (idx, item) { 48749 var $holder = $$1(item); 48750 $holder.append(_this.ui.palette({ 48751 colors: customColors, 48752 colorsName: customColors, 48753 eventName: $holder.data('event'), 48754 container: _this.options.container, 48755 tooltip: _this.options.tooltip 48756 }).render()); 48757 }); 48758 $dropdown.find('input[type=color]').each(function (idx, item) { 48759 $$1(item).change(function () { 48760 var $chip = $dropdown.find('#' + $$1(this).data('event')).find('.note-color-btn').first(); 48761 var color = this.value.toUpperCase(); 48762 $chip.css('background-color', color) 48763 .attr('aria-label', color) 48764 .attr('data-value', color) 48765 .attr('data-original-title', color); 48766 $chip.click(); 48767 }); 48768 }); 48769 }, 48770 click: function (event) { 48771 event.stopPropagation(); 48772 var $parent = $$1('.' + className); 48773 var $button = $$1(event.target); 48774 var eventName = $button.data('event'); 48775 var value = $button.attr('data-value'); 48776 if (eventName === 'openPalette') { 48777 var $picker = $parent.find('#' + value); 48778 var $palette = $$1($parent.find('#' + $picker.data('event')).find('.note-color-row')[0]); 48779 // Shift palette chips 48780 var $chip = $palette.find('.note-color-btn').last().detach(); 48781 // Set chip attributes 48782 var color = $picker.val(); 48783 $chip.css('background-color', color) 48784 .attr('aria-label', color) 48785 .attr('data-value', color) 48786 .attr('data-original-title', color);
48787 $palette.prepend($chip); 48788 $picker.click(); 48789 } 48790 else if (lists.contains(['backColor', 'foreColor'], eventName)) { 48791 var key = eventName === 'backColor' ? 'background-color' : 'color'; 48792 var $color = $button.closest('.note-color').find('.note-recent-color'); 48793 var $currentButton = $button.closest('.note-color').find('.note-current-color-button'); 48794 $color.css(key, value); 48795 $currentButton.attr('data-' + eventName, value); 48796 _this.context.invoke('editor.' + eventName, value); 48797 } 48798 } 48799 }), 48800 ] 48801 }).render(); 48802 }; 48803 Buttons.prototype.addToolbarButtons = function () { 48804 var _this = this; 48805 this.context.memo('button.style', function () { 48806 return _this.ui.buttonGroup([ 48807 _this.button({ 48808 className: 'dropdown-toggle', 48809 contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.magic), _this.options), 48810 tooltip: _this.lang.style.style, 48811 data: { 48812 toggle: 'dropdown' 48813 } 48814 }), 48815 _this.ui.dropdown({ 48816 className: 'dropdown-style', 48817 items: _this.options.styleTags, 48818 title: _this.lang.style.style, 48819 template: function (item) { 48820 if (typeof item === 'string') { 48821 item = { tag: item, title: (_this.lang.style.hasOwnProperty(item) ? _this.lang.style[item] : item) }; 48822 } 48823 var tag = item.tag; 48824 var title = item.title; 48825 var style = item.style ? ' style="' + item.style + '" ' : ''; 48826 var className = item.className ? ' class="' + item.className + '"' : ''; 48827 return '<' + tag + style + className + '>' + title + '</' + tag + '>'; 48828 }, 48829 click: _this.context.createInvokeHandler('editor.formatBlock') 48830 }), 48831 ]).render(); 48832 }); 48833 var _loop_1 = function (styleIdx, styleLen) { 48834 var item = this_1.options.styleTags[styleIdx]; 48835 this_1.context.memo('button.style.' + item, function () { 48836 return _this.button({ 48837 className: 'note-btn-style-' + item, 48838 contents: '<div data-value="' + item + '">' + item.toUpperCase() + '</div>', 48839 tooltip: _this.lang.style[item], 48840 click: _this.context.createInvokeHandler('editor.formatBlock') 48841 }).render(); 48842 }); 48843 }; 48844 var this_1 = this; 48845 for (var styleIdx = 0, styleLen = this.options.styleTags.length; styleIdx < styleLen; styleIdx++) { 48846 _loop_1(styleIdx, styleLen); 48847 } 48848 this.context.memo('button.bold', function () { 48849 return _this.button({ 48850 className: 'note-btn-bold', 48851 contents: _this.ui.icon(_this.options.icons.bold), 48852 tooltip: _this.lang.font.bold + _this.representShortcut('bold'), 48853 click: _this.context.createInvokeHandlerAndUpdateState('editor.bold') 48854 }).render(); 48855 }); 48856 this.context.memo('button.italic', function () { 48857 return _this.button({ 48858 className: 'note-btn-italic', 48859 contents: _this.ui.icon(_this.options.icons.italic), 48860 tooltip: _this.lang.font.italic + _this.representShortcut('italic'), 48861 click: _this.context.createInvokeHandlerAndUpdateState('editor.italic') 48862 }).render(); 48863 }); 48864 this.context.memo('button.underline', function () { 48865 return _this.button({ 48866 className: 'note-btn-underline', 48867 contents: _this.ui.icon(_this.options.icons.underline), 48868 tooltip: _this.lang.font.underline + _this.representShortcut('underline'), 48869 click: _this.context.createInvokeHandlerAndUpdateState('editor.underline') 48870 }).render(); 48871 }); 48872 this.context.memo('button.clear', function () { 48873 return _this.button({ 48874 contents: _this.ui.icon(_this.options.icons.eraser), 48875 tooltip: _this.lang.font.clear + _this.representShortcut('removeFormat'), 48876 click: _this.context.createInvokeHandler('editor.removeFormat') 48877 }).render(); 48878 }); 48879 this.context.memo('button.strikethrough', function () { 48880 return _this.button({ 48881 className: 'note-btn-strikethrough', 48882 contents: _this.ui.icon(_this.options.icons.strikethrough), 48883 tooltip: _this.lang.font.strikethrough + _this.representShortcut('strikethrough'), 48884 click: _this.context.createInvokeHandlerAndUpdateState('editor.strikethrough') 48885 }).render(); 48886 }); 48887 this.context.memo('button.superscript', function () { 48888 return _this.button({ 48889 className: 'note-btn-superscript', 48890 contents: _this.ui.icon(_this.options.icons.superscript), 48891 tooltip: _this.lang.font.superscript, 48892 click: _this.context.createInvokeHandlerAndUpdateState('editor.superscript') 48893 }).render(); 48894 }); 48895 this.context.memo('button.subscript', function () { 48896 return _this.button({ 48897 className: 'note-btn-subscript', 48898 contents: _this.ui.icon(_this.options.icons.subscript), 48899 tooltip: _this.lang.font.subscript, 48900 click: _this.context.createInvokeHandlerAndUpdateState('editor.subscript') 48901 }).render(); 48902 }); 48903 this.context.memo('button.fontname', function () {
vendor: 16,384 bytes, lines 48904-49222
48904 var styleInfo = _this.context.invoke('editor.currentStyle'); 48905 // Add 'default' fonts into the fontnames array if not exist 48906 $$1.each(styleInfo['font-family'].split(','), function (idx, fontname) { 48907 fontname = fontname.trim().replace(/['"]+/g, ''); 48908 if (_this.isFontDeservedToAdd(fontname)) { 48909 if (_this.options.fontNames.indexOf(fontname) === -1) { 48910 _this.options.fontNames.push(fontname); 48911 } 48912 } 48913 }); 48914 return _this.ui.buttonGroup([ 48915 _this.button({ 48916 className: 'dropdown-toggle', 48917 contents: _this.ui.dropdownButtonContents('<span class="note-current-fontname"/>', _this.options), 48918 tooltip: _this.lang.font.name, 48919 data: { 48920 toggle: 'dropdown' 48921 } 48922 }), 48923 _this.ui.dropdownCheck({ 48924 className: 'dropdown-fontname', 48925 checkClassName: _this.options.icons.menuCheck, 48926 items: _this.options.fontNames.filter(_this.isFontInstalled.bind(_this)), 48927 title: _this.lang.font.name, 48928 template: function (item) { 48929 return '<span style="font-family: \'' + item + '\'">' + item + '</span>'; 48930 }, 48931 click: _this.context.createInvokeHandlerAndUpdateState('editor.fontName') 48932 }), 48933 ]).render(); 48934 }); 48935 this.context.memo('button.fontsize', function () { 48936 return _this.ui.buttonGroup([ 48937 _this.button({ 48938 className: 'dropdown-toggle', 48939 contents: _this.ui.dropdownButtonContents('<span class="note-current-fontsize"/>', _this.options), 48940 tooltip: _this.lang.font.size, 48941 data: { 48942 toggle: 'dropdown' 48943 } 48944 }), 48945 _this.ui.dropdownCheck({ 48946 className: 'dropdown-fontsize', 48947 checkClassName: _this.options.icons.menuCheck, 48948 items: _this.options.fontSizes, 48949 title: _this.lang.font.size, 48950 click: _this.context.createInvokeHandlerAndUpdateState('editor.fontSize') 48951 }), 48952 ]).render(); 48953 }); 48954 this.context.memo('button.color', function () { 48955 return _this.colorPalette('note-color-all', _this.lang.color.recent, true, true); 48956 }); 48957 this.context.memo('button.forecolor', function () { 48958 return _this.colorPalette('note-color-fore', _this.lang.color.foreground, false, true); 48959 }); 48960 this.context.memo('button.backcolor', function () { 48961 return _this.colorPalette('note-color-back', _this.lang.color.background, true, false); 48962 }); 48963 this.context.memo('button.ul', function () { 48964 return _this.button({ 48965 contents: _this.ui.icon(_this.options.icons.unorderedlist), 48966 tooltip: _this.lang.lists.unordered + _this.representShortcut('insertUnorderedList'), 48967 click: _this.context.createInvokeHandler('editor.insertUnorderedList') 48968 }).render(); 48969 }); 48970 this.context.memo('button.ol', function () { 48971 return _this.button({ 48972 contents: _this.ui.icon(_this.options.icons.orderedlist), 48973 tooltip: _this.lang.lists.ordered + _this.representShortcut('insertOrderedList'), 48974 click: _this.context.createInvokeHandler('editor.insertOrderedList') 48975 }).render(); 48976 }); 48977 var justifyLeft = this.button({ 48978 contents: this.ui.icon(this.options.icons.alignLeft), 48979 tooltip: this.lang.paragraph.left + this.representShortcut('justifyLeft'), 48980 click: this.context.createInvokeHandler('editor.justifyLeft') 48981 }); 48982 var justifyCenter = this.button({ 48983 contents: this.ui.icon(this.options.icons.alignCenter), 48984 tooltip: this.lang.paragraph.center + this.representShortcut('justifyCenter'), 48985 click: this.context.createInvokeHandler('editor.justifyCenter') 48986 }); 48987 var justifyRight = this.button({ 48988 contents: this.ui.icon(this.options.icons.alignRight), 48989 tooltip: this.lang.paragraph.right + this.representShortcut('justifyRight'), 48990 click: this.context.createInvokeHandler('editor.justifyRight') 48991 }); 48992 var justifyFull = this.button({ 48993 contents: this.ui.icon(this.options.icons.alignJustify), 48994 tooltip: this.lang.paragraph.justify + this.representShortcut('justifyFull'), 48995 click: this.context.createInvokeHandler('editor.justifyFull') 48996 }); 48997 var outdent = this.button({ 48998 contents: this.ui.icon(this.options.icons.outdent), 48999 tooltip: this.lang.paragraph.outdent + this.representShortcut('outdent'), 49000 click: this.context.createInvokeHandler('editor.outdent') 49001 }); 49002 var indent = this.button({ 49003 contents: this.ui.icon(this.options.icons.indent), 49004 tooltip: this.lang.paragraph.indent + this.representShortcut('indent'), 49005 click: this.context.createInvokeHandler('editor.indent') 49006 }); 49007 this.context.memo('button.justifyLeft', func.invoke(justifyLeft, 'render')); 49008 this.context.memo('button.justifyCenter', func.invoke(justifyCenter, 'render')); 49009 this.context.memo('button.justifyRight', func.invoke(justifyRight, 'render')); 49010 this.context.memo('button.justifyFull', func.invoke(justifyFull, 'render')); 49011 this.context.memo('button.outdent', func.invoke(outdent, 'render')); 49012 this.context.memo('button.indent', func.invoke(indent, 'render')); 49013 this.context.memo('button.paragraph', function () { 49014 return _this.ui.buttonGroup([ 49015 _this.button({ 49016 className: 'dropdown-toggle', 49017 contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.alignLeft), _this.options), 49018 tooltip: _this.lang.paragraph.paragraph, 49019 data: { 49020 toggle: 'dropdown' 49021 } 49022 }), 49023 _this.ui.dropdown([ 49024 _this.ui.buttonGroup({ 49025 className: 'note-align', 49026 children: [justifyLeft, justifyCenter, justifyRight, justifyFull] 49027 }), 49028 _this.ui.buttonGroup({ 49029 className: 'note-list', 49030 children: [outdent, indent] 49031 }), 49032 ]), 49033 ]).render(); 49034 }); 49035 this.context.memo('button.height', function () { 49036 return _this.ui.buttonGroup([ 49037 _this.button({ 49038 className: 'dropdown-toggle', 49039 contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.textHeight), _this.options), 49040 tooltip: _this.lang.font.height, 49041 data: { 49042 toggle: 'dropdown' 49043 } 49044 }), 49045 _this.ui.dropdownCheck({ 49046 items: _this.options.lineHeights, 49047 checkClassName: _this.options.icons.menuCheck, 49048 className: 'dropdown-line-height', 49049 title: _this.lang.font.height, 49050 click: _this.context.createInvokeHandler('editor.lineHeight') 49051 }), 49052 ]).render(); 49053 }); 49054 this.context.memo('button.table', function () { 49055 return _this.ui.buttonGroup([ 49056 _this.button({ 49057 className: 'dropdown-toggle', 49058 contents: _this.ui.dropdownButtonContents(_this.ui.icon(_this.options.icons.table), _this.options), 49059 tooltip: _this.lang.table.table, 49060 data: { 49061 toggle: 'dropdown' 49062 } 49063 }), 49064 _this.ui.dropdown({ 49065 title: _this.lang.table.table, 49066 className: 'note-table', 49067 items: [ 49068 '<div class="note-dimension-picker">', 49069 ' <div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"/>', 49070 ' <div class="note-dimension-picker-highlighted"/>', 49071 ' <div class="note-dimension-picker-unhighlighted"/>', 49072 '</div>', 49073 '<div class="note-dimension-display">1 x 1</div>', 49074 ].join('') 49075 }), 49076 ], { 49077 callback: function ($node) { 49078 var $catcher = $node.find('.note-dimension-picker-mousecatcher'); 49079 $catcher.css({ 49080 width: _this.options.insertTableMaxSize.col + 'em', 49081 height: _this.options.insertTableMaxSize.row + 'em' 49082 }).mousedown(_this.context.createInvokeHandler('editor.insertTable')) 49083 .on('mousemove', _this.tableMoveHandler.bind(_this)); 49084 } 49085 }).render(); 49086 }); 49087 this.context.memo('button.link', function () { 49088 return _this.button({ 49089 contents: _this.ui.icon(_this.options.icons.link), 49090 tooltip: _this.lang.link.link + _this.representShortcut('linkDialog.show'), 49091 click: _this.context.createInvokeHandler('linkDialog.show') 49092 }).render(); 49093 }); 49094 this.context.memo('button.picture', function () { 49095 return _this.button({ 49096 contents: _this.ui.icon(_this.options.icons.picture), 49097 tooltip: _this.lang.image.image, 49098 click: _this.context.createInvokeHandler('imageDialog.show') 49099 }).render(); 49100 }); 49101 this.context.memo('button.video', function () { 49102 return _this.button({ 49103 contents: _this.ui.icon(_this.options.icons.video), 49104 tooltip: _this.lang.video.video, 49105 click: _this.context.createInvokeHandler('videoDialog.show') 49106 }).render(); 49107 }); 49108 this.context.memo('button.hr', function () { 49109 return _this.button({ 49110 contents: _this.ui.icon(_this.options.icons.minus), 49111 tooltip: _this.lang.hr.insert + _this.representShortcut('insertHorizontalRule'), 49112 click: _this.context.createInvokeHandler('editor.insertHorizontalRule') 49113 }).render(); 49114 }); 49115 this.context.memo('button.fullscreen', function () { 49116 return _this.button({ 49117 className: 'btn-fullscreen', 49118 contents: _this.ui.icon(_this.options.icons.arrowsAlt), 49119 tooltip: _this.lang.options.fullscreen, 49120 click: _this.context.createInvokeHandler('fullscreen.toggle') 49121 }).render(); 49122 }); 49123 this.context.memo('button.codeview', function () { 49124 return _this.button({ 49125 className: 'btn-codeview', 49126 contents: _this.ui.icon(_this.options.icons.code), 49127 tooltip: _this.lang.options.codeview, 49128 click: _this.context.createInvokeHandler('codeview.toggle') 49129 }).render(); 49130 }); 49131 this.context.memo('button.redo', function () { 49132 return _this.button({ 49133 contents: _this.ui.icon(_this.options.icons.redo), 49134 tooltip: _this.lang.history.redo + _this.representShortcut('redo'), 49135 click: _this.context.createInvokeHandler('editor.redo') 49136 }).render(); 49137 }); 49138 this.context.memo('button.undo', function () { 49139 return _this.button({ 49140 contents: _this.ui.icon(_this.options.icons.undo), 49141 tooltip: _this.lang.history.undo + _this.representShortcut('undo'), 49142 click: _this.context.createInvokeHandler('editor.undo') 49143 }).render(); 49144 }); 49145 this.context.memo('button.help', function () { 49146 return _this.button({ 49147 contents: _this.ui.icon(_this.options.icons.question), 49148 tooltip: _this.lang.options.help, 49149 click: _this.context.createInvokeHandler('helpDialog.show') 49150 }).render(); 49151 }); 49152 }; 49153 /** 49154 * image: [ 49155 * ['imageResize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']], 49156 * ['float', ['floatLeft', 'floatRight', 'floatNone']], 49157 * ['remove', ['removeMedia']], 49158 * ], 49159 */ 49160 Buttons.prototype.addImagePopoverButtons = function () { 49161 var _this = this; 49162 // Image Size Buttons 49163 this.context.memo('button.resizeFull', function () { 49164 return _this.button({ 49165 contents: '<span class="note-fontsize-10">100%</span>', 49166 tooltip: _this.lang.image.resizeFull, 49167 click: _this.context.createInvokeHandler('editor.resize', '1') 49168 }).render(); 49169 }); 49170 this.context.memo('button.resizeHalf', function () { 49171 return _this.button({ 49172 contents: '<span class="note-fontsize-10">50%</span>', 49173 tooltip: _this.lang.image.resizeHalf, 49174 click: _this.context.createInvokeHandler('editor.resize', '0.5') 49175 }).render(); 49176 }); 49177 this.context.memo('button.resizeQuarter', function () { 49178 return _this.button({ 49179 contents: '<span class="note-fontsize-10">25%</span>', 49180 tooltip: _this.lang.image.resizeQuarter, 49181 click: _this.context.createInvokeHandler('editor.resize', '0.25') 49182 }).render(); 49183 }); 49184 this.context.memo('button.resizeNone', function () { 49185 return _this.button({ 49186 contents: _this.ui.icon(_this.options.icons.rollback), 49187 tooltip: _this.lang.image.resizeNone, 49188 click: _this.context.createInvokeHandler('editor.resize', '0') 49189 }).render(); 49190 }); 49191 // Float Buttons 49192 this.context.memo('button.floatLeft', function () { 49193 return _this.button({ 49194 contents: _this.ui.icon(_this.options.icons.floatLeft), 49195 tooltip: _this.lang.image.floatLeft, 49196 click: _this.context.createInvokeHandler('editor.floatMe', 'left') 49197 }).render(); 49198 }); 49199 this.context.memo('button.floatRight', function () { 49200 return _this.button({ 49201 contents: _this.ui.icon(_this.options.icons.floatRight), 49202 tooltip: _this.lang.image.floatRight, 49203 click: _this.context.createInvokeHandler('editor.floatMe', 'right') 49204 }).render(); 49205 }); 49206 this.context.memo('button.floatNone', function () { 49207 return _this.button({ 49208 contents: _this.ui.icon(_this.options.icons.rollback), 49209 tooltip: _this.lang.image.floatNone, 49210 click: _this.context.createInvokeHandler('editor.floatMe', 'none') 49211 }).render(); 49212 }); 49213 // Remove Buttons 49214 this.context.memo('button.removeMedia', function () { 49215 return _this.button({ 49216 contents: _this.ui.icon(_this.options.icons.trash), 49217 tooltip: _this.lang.image.remove, 49218 click: _this.context.createInvokeHandler('editor.removeMedia') 49219 }).render(); 49220 }); 49221 }; 49222 Buttons.prototype.addLinkPopoverButtons = function () {
49223 var _this = this; 49224 this.context.memo('button.linkDialogShow', function () { 49225 return _this.button({ 49226 contents: _this.ui.icon(_this.options.icons.link), 49227 tooltip: _this.lang.link.edit, 49228 click: _this.context.createInvokeHandler('linkDialog.show') 49229 }).render(); 49230 }); 49231 this.context.memo('button.unlink', function () { 49232 return _this.button({ 49233 contents: _this.ui.icon(_this.options.icons.unlink), 49234 tooltip: _this.lang.link.unlink, 49235 click: _this.context.createInvokeHandler('editor.unlink') 49236 }).render(); 49237 }); 49238 }; 49239 /** 49240 * table : [ 49241 * ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']], 49242 * ['delete', ['deleteRow', 'deleteCol', 'deleteTable']] 49243 * ], 49244 */ 49245 Buttons.prototype.addTablePopoverButtons = function () { 49246 var _this = this; 49247 this.context.memo('button.addRowUp', function () { 49248 return _this.button({ 49249 className: 'btn-md', 49250 contents: _this.ui.icon(_this.options.icons.rowAbove), 49251 tooltip: _this.lang.table.addRowAbove, 49252 click: _this.context.createInvokeHandler('editor.addRow', 'top') 49253 }).render(); 49254 }); 49255 this.context.memo('button.addRowDown', function () { 49256 return _this.button({ 49257 className: 'btn-md', 49258 contents: _this.ui.icon(_this.options.icons.rowBelow), 49259 tooltip: _this.lang.table.addRowBelow, 49260 click: _this.context.createInvokeHandler('editor.addRow', 'bottom') 49261 }).render(); 49262 }); 49263 this.context.memo('button.addColLeft', function () { 49264 return _this.button({ 49265 className: 'btn-md', 49266 contents: _this.ui.icon(_this.options.icons.colBefore), 49267 tooltip: _this.lang.table.addColLeft, 49268 click: _this.context.createInvokeHandler('editor.addCol', 'left') 49269 }).render(); 49270 }); 49271 this.context.memo('button.addColRight', function () { 49272 return _this.button({ 49273 className: 'btn-md', 49274 contents: _this.ui.icon(_this.options.icons.colAfter), 49275 tooltip: _this.lang.table.addColRight, 49276 click: _this.context.createInvokeHandler('editor.addCol', 'right') 49277 }).render(); 49278 }); 49279 this.context.memo('button.deleteRow', function () { 49280 return _this.button({ 49281 className: 'btn-md', 49282 contents: _this.ui.icon(_this.options.icons.rowRemove), 49283 tooltip: _this.lang.table.delRow, 49284 click: _this.context.createInvokeHandler('editor.deleteRow') 49285 }).render(); 49286 }); 49287 this.context.memo('button.deleteCol', function () { 49288 return _this.button({ 49289 className: 'btn-md', 49290 contents: _this.ui.icon(_this.options.icons.colRemove), 49291 tooltip: _this.lang.table.delCol, 49292 click: _this.context.createInvokeHandler('editor.deleteCol') 49293 }).render(); 49294 }); 49295 this.context.memo('button.deleteTable', function () { 49296 return _this.button({ 49297 className: 'btn-md', 49298 contents: _this.ui.icon(_this.options.icons.trash), 49299 tooltip: _this.lang.table.delTable, 49300 click: _this.context.createInvokeHandler('editor.deleteTable') 49301 }).render(); 49302 }); 49303 }; 49304 Buttons.prototype.build = function ($container, groups) { 49305 for (var groupIdx = 0, groupLen = groups.length; groupIdx < groupLen; groupIdx++) { 49306 var group = groups[groupIdx]; 49307 var groupName = Array.isArray(group) ? group[0] : group; 49308 var buttons = Array.isArray(group) ? ((group.length === 1) ? [group[0]] : group[1]) : [group]; 49309 var $group = this.ui.buttonGroup({ 49310 className: 'note-' + groupName 49311 }).render(); 49312 for (var idx = 0, len = buttons.length; idx < len; idx++) { 49313 var btn = this.context.memo('button.' + buttons[idx]); 49314 if (btn) { 49315 $group.append(typeof btn === 'function' ? btn() : btn); 49316 } 49317 } 49318 $group.appendTo($container); 49319 } 49320 }; 49321 /** 49322 * @param {jQuery} [$container] 49323 */ 49324 Buttons.prototype.updateCurrentStyle = function ($container) { 49325 var _this = this; 49326 var $cont = $container || this.$toolbar;
49327 var styleInfo = this.context.invoke('editor.currentStyle'); 49328 this.updateBtnStates($cont, { 49329 '.note-btn-bold': function () { 49330 return styleInfo['font-bold'] === 'bold'; 49331 }, 49332 '.note-btn-italic': function () { 49333 return styleInfo['font-italic'] === 'italic'; 49334 }, 49335 '.note-btn-underline': function () { 49336 return styleInfo['font-underline'] === 'underline'; 49337 }, 49338 '.note-btn-subscript': function () { 49339 return styleInfo['font-subscript'] === 'subscript'; 49340 }, 49341 '.note-btn-superscript': function () { 49342 return styleInfo['font-superscript'] === 'superscript'; 49343 }, 49344 '.note-btn-strikethrough': function () { 49345 return styleInfo['font-strikethrough'] === 'strikethrough'; 49346 } 49347 }); 49348 if (styleInfo['font-family']) { 49349 var fontNames = styleInfo['font-family'].split(',').map(function (name) { 49350 return name.replace(/[\'\"]/g, '') 49351 .replace(/\s+$/, '') 49352 .replace(/^\s+/, ''); 49353 }); 49354 var fontName_1 = lists.find(fontNames, this.isFontInstalled.bind(this)); 49355 $cont.find('.dropdown-fontname a').each(function (idx, item) { 49356 var $item = $$1(item); 49357 // always compare string to avoid creating another func. 49358 var isChecked = ($item.data('value') + '') === (fontName_1 + ''); 49359 $item.toggleClass('checked', isChecked); 49360 }); 49361 $cont.find('.note-current-fontname').text(fontName_1).css('font-family', fontName_1); 49362 } 49363 if (styleInfo['font-size']) { 49364 var fontSize_1 = styleInfo['font-size']; 49365 $cont.find('.dropdown-fontsize a').each(function (idx, item) { 49366 var $item = $$1(item); 49367 // always compare with string to avoid creating another func. 49368 var isChecked = ($item.data('value') + '') === (fontSize_1 + ''); 49369 $item.toggleClass('checked', isChecked); 49370 }); 49371 $cont.find('.note-current-fontsize').text(fontSize_1); 49372 } 49373 if (styleInfo['line-height']) { 49374 var lineHeight_1 = styleInfo['line-height']; 49375 $cont.find('.dropdown-line-height li a').each(function (idx, item) { 49376 // always compare with string to avoid creating another func. 49377 var isChecked = ($$1(item).data('value') + '') === (lineHeight_1 + ''); 49378 _this.className = isChecked ? 'checked' : ''; 49379 }); 49380 } 49381 }; 49382 Buttons.prototype.updateBtnStates = function ($container, infos) { 49383 var _this = this; 49384 $$1.each(infos, function (selector, pred) { 49385 _this.ui.toggleBtnActive($container.find(selector), pred()); 49386 }); 49387 }; 49388 Buttons.prototype.tableMoveHandler = function (event) { 49389 var PX_PER_EM = 18; 49390 var $picker = $$1(event.target.parentNode); // target is mousecatcher 49391 var $dimensionDisplay = $picker.next(); 49392 var $catcher = $picker.find('.note-dimension-picker-mousecatcher'); 49393 var $highlighted = $picker.find('.note-dimension-picker-highlighted'); 49394 var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted'); 49395 var posOffset; 49396 // HTML5 with jQuery - e.offsetX is undefined in Firefox 49397 if (event.offsetX === undefined) { 49398 var posCatcher = $$1(event.target).offset(); 49399 posOffset = { 49400 x: event.pageX - posCatcher.left, 49401 y: event.pageY - posCatcher.top 49402 }; 49403 } 49404 else { 49405 posOffset = { 49406 x: event.offsetX, 49407 y: event.offsetY 49408 }; 49409 } 49410 var dim = { 49411 c: Math.ceil(posOffset.x / PX_PER_EM) || 1,
49412 r: Math.ceil(posOffset.y / PX_PER_EM) || 1 49413 }; 49414 $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' }); 49415 $catcher.data('value', dim.c + 'x' + dim.r); 49416 if (dim.c > 3 && dim.c < this.options.insertTableMaxSize.col) { 49417 $unhighlighted.css({ width: dim.c + 1 + 'em' }); 49418 } 49419 if (dim.r > 3 && dim.r < this.options.insertTableMaxSize.row) { 49420 $unhighlighted.css({ height: dim.r + 1 + 'em' }); 49421 } 49422 $dimensionDisplay.html(dim.c + ' x ' + dim.r); 49423 }; 49424 return Buttons; 49425 }()); 49426 49427 var Toolbar = /** @class */ (function () { 49428 function Toolbar(context) { 49429 this.context = context; 49430 this.$window = $$1(window); 49431 this.$document = $$1(document); 49432 this.ui = $$1.summernote.ui; 49433 this.$note = context.layoutInfo.note; 49434 this.$editor = context.layoutInfo.editor; 49435 this.$toolbar = context.layoutInfo.toolbar; 49436 this.$editable = context.layoutInfo.editable; 49437 this.$statusbar = context.layoutInfo.statusbar; 49438 this.options = context.options; 49439 this.isFollowing = false; 49440 this.followScroll = this.followScroll.bind(this); 49441 } 49442 Toolbar.prototype.shouldInitialize = function () { 49443 return !this.options.airMode; 49444 }; 49445 Toolbar.prototype.initialize = function () { 49446 var _this = this; 49447 this.options.toolbar = this.options.toolbar || []; 49448 if (!this.options.toolbar.length) { 49449 this.$toolbar.hide(); 49450 } 49451 else { 49452 this.context.invoke('buttons.build', this.$toolbar, this.options.toolbar); 49453 } 49454 if (this.options.toolbarContainer) { 49455 this.$toolbar.appendTo(this.options.toolbarContainer); 49456 } 49457 this.changeContainer(false); 49458 this.$note.on('summernote.keyup summernote.mouseup summernote.change', function () { 49459 _this.context.invoke('buttons.updateCurrentStyle'); 49460 }); 49461 this.context.invoke('buttons.updateCurrentStyle'); 49462 if (this.options.followingToolbar) { 49463 this.$window.on('scroll resize', this.followScroll); 49464 } 49465 }; 49466 Toolbar.prototype.destroy = function () { 49467 this.$toolbar.children().remove(); 49468 if (this.options.followingToolbar) { 49469 this.$window.off('scroll resize', this.followScroll); 49470 } 49471 }; 49472 Toolbar.prototype.followScroll = function () { 49473 if (this.$editor.hasClass('fullscreen')) { 49474 return false; 49475 } 49476 var editorHeight = this.$editor.outerHeight(); 49477 var editorWidth = this.$editor.width(); 49478 var toolbarHeight = this.$toolbar.height(); 49479 var statusbarHeight = this.$statusbar.height(); 49480 // check if the web app is currently using another static bar 49481 var otherBarHeight = 0; 49482 if (this.options.otherStaticBar) { 49483 otherBarHeight = $$1(this.options.otherStaticBar).outerHeight(); 49484 } 49485 var currentOffset = this.$document.scrollTop(); 49486 var editorOffsetTop = this.$editor.offset().top; 49487 var editorOffsetBottom = editorOffsetTop + editorHeight; 49488 var activateOffset = editorOffsetTop - otherBarHeight; 49489 var deactivateOffsetBottom = editorOffsetBottom - otherBarHeight - toolbarHeight - statusbarHeight; 49490 if (!this.isFollowing && 49491 (currentOffset > activateOffset) && (currentOffset < deactivateOffsetBottom - toolbarHeight)) { 49492 this.isFollowing = true; 49493 this.$toolbar.css({ 49494 position: 'fixed', 49495 top: otherBarHeight, 49496 width: editorWidth 49497 }); 49498 this.$editable.css({ 49499 marginTop: this.$toolbar.height() + 5 49500 }); 49501 } 49502 else if (this.isFollowing && 49503 ((currentOffset < activateOffset) || (currentOffset > deactivateOffsetBottom))) { 49504 this.isFollowing = false; 49505 this.$toolbar.css({ 49506 position: 'relative', 49507 top: 0, 49508 width: '100%' 49509 }); 49510 this.$editable.css({ 49511 marginTop: '' 49512 }); 49513 } 49514 }; 49515 Toolbar.prototype.changeContainer = function (isFullscreen) { 49516 if (isFullscreen) {
49517 this.$toolbar.prependTo(this.$editor); 49518 } 49519 else { 49520 if (this.options.toolbarContainer) { 49521 this.$toolbar.appendTo(this.options.toolbarContainer); 49522 } 49523 } 49524 this.followScroll(); 49525 }; 49526 Toolbar.prototype.updateFullscreen = function (isFullscreen) { 49527 this.ui.toggleBtnActive(this.$toolbar.find('.btn-fullscreen'), isFullscreen); 49528 this.changeContainer(isFullscreen); 49529 }; 49530 Toolbar.prototype.updateCodeview = function (isCodeview) { 49531 this.ui.toggleBtnActive(this.$toolbar.find('.btn-codeview'), isCodeview); 49532 if (isCodeview) { 49533 this.deactivate(); 49534 } 49535 else { 49536 this.activate(); 49537 } 49538 }; 49539 Toolbar.prototype.activate = function (isIncludeCodeview) { 49540 var $btn = this.$toolbar.find('button'); 49541 if (!isIncludeCodeview) { 49542 $btn = $btn.not('.btn-codeview'); 49543 } 49544 this.ui.toggleBtn($btn, true); 49545 }; 49546 Toolbar.prototype.deactivate = function (isIncludeCodeview) { 49547 var $btn = this.$toolbar.find('button'); 49548 if (!isIncludeCodeview) { 49549 $btn = $btn.not('.btn-codeview'); 49550 } 49551 this.ui.toggleBtn($btn, false); 49552 }; 49553 return Toolbar; 49554 }()); 49555 49556 var LinkDialog = /** @class */ (function () { 49557 function LinkDialog(context) { 49558 this.context = context; 49559 this.ui = $$1.summernote.ui; 49560 this.$body = $$1(document.body); 49561 this.$editor = context.layoutInfo.editor; 49562 this.options = context.options; 49563 this.lang = this.options.langInfo; 49564 context.memo('help.linkDialog.show', this.options.langInfo.help['linkDialog.show']); 49565 } 49566 LinkDialog.prototype.initialize = function () { 49567 var $container = this.options.dialogsInBody ? this.$body : this.$editor; 49568 var body = [ 49569 '<div class="form-group note-form-group">', 49570 "<label class=\"note-form-label\">" + this.lang.link.textToDisplay + "</label>", 49571 '<input class="note-link-text form-control note-form-control note-input" type="text" />', 49572 '</div>', 49573 '<div class="form-group note-form-group">', 49574 "<label class=\"note-form-label\">" + this.lang.link.url + "</label>", 49575 '<input class="note-link-url form-control note-form-control note-input" type="text" value="http://" />', 49576 '</div>', 49577 !this.options.disableLinkTarget 49578 ? $$1('<div/>').append(this.ui.checkbox({ 49579 className: 'sn-checkbox-open-in-new-window', 49580 text: this.lang.link.openInNewWindow, 49581 checked: true 49582 }).render()).html() 49583 : '', 49584 ].join(''); 49585 var buttonClass = 'btn btn-primary note-btn note-btn-primary note-link-btn'; 49586 var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.link.insert + "\" disabled>"; 49587 this.$dialog = this.ui.dialog({ 49588 className: 'link-dialog', 49589 title: this.lang.link.insert, 49590 fade: this.options.dialogsFade, 49591 body: body, 49592 footer: footer 49593 }).render().appendTo($container); 49594 }; 49595 LinkDialog.prototype.destroy = function () { 49596 this.ui.hideDialog(this.$dialog); 49597 this.$dialog.remove(); 49598 }; 49599 LinkDialog.prototype.bindEnterKey = function ($input, $btn) { 49600 $input.on('keypress', function (event) { 49601 if (event.keyCode === key.code.ENTER) { 49602 event.preventDefault(); 49603 $btn.trigger('click'); 49604 } 49605 }); 49606 }; 49607 /** 49608 * toggle update button 49609 */ 49610 LinkDialog.prototype.toggleLinkBtn = function ($linkBtn, $linkText, $linkUrl) { 49611 this.ui.toggleBtn($linkBtn, $linkText.val() && $linkUrl.val()); 49612 }; 49613 /** 49614 * Show link dialog and set event handlers on dialog controls. 49615 * 49616 * @param {Object} linkInfo 49617 * @return {Promise} 49618 */ 49619 LinkDialog.prototype.showLinkDialog = function (linkInfo) { 49620 var _this = this; 49621 return $$1.Deferred(function (deferred) { 49622 var $linkText = _this.$dialog.find('.note-link-text'); 49623 var $linkUrl = _this.$dialog.find('.note-link-url'); 49624 var $linkBtn = _this.$dialog.find('.note-link-btn'); 49625 var $openInNewWindow = _this.$dialog 49626 .find('.sn-checkbox-open-in-new-window input[type=checkbox]'); 49627 _this.ui.onDialogShown(_this.$dialog, function () { 49628 _this.context.triggerEvent('dialog.shown'); 49629 // If no url was given and given text is valid URL then copy that into URL Field 49630 if (!linkInfo.url && func.isValidUrl(linkInfo.text)) { 49631 linkInfo.url = linkInfo.text; 49632 } 49633 $linkText.on('input paste propertychange', function () { 49634 // If linktext was modified by input events, 49635 // cloning text from linkUrl will be stopped. 49636 linkInfo.text = $linkText.val(); 49637 _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl); 49638 }).val(linkInfo.text); 49639 $linkUrl.on('input paste propertychange', function () { 49640 // Display same text on `Text to display` as default 49641 // when linktext has no text 49642 if (!linkInfo.text) { 49643 $linkText.val($linkUrl.val()); 49644 } 49645 _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl); 49646 }).val(linkInfo.url); 49647 if (!env.isSupportTouch) { 49648 $linkUrl.trigger('focus'); 49649 } 49650 _this.toggleLinkBtn($linkBtn, $linkText, $linkUrl); 49651 _this.bindEnterKey($linkUrl, $linkBtn); 49652 _this.bindEnterKey($linkText, $linkBtn); 49653 var isNewWindowChecked = linkInfo.isNewWindow !== undefined 49654 ? linkInfo.isNewWindow : _this.context.options.linkTargetBlank; 49655 $openInNewWindow.prop('checked', isNewWindowChecked); 49656 $linkBtn.one('click', function (event) { 49657 event.preventDefault(); 49658 deferred.resolve({ 49659 range: linkInfo.range, 49660 url: $linkUrl.val(), 49661 text: $linkText.val(), 49662 isNewWindow: $openInNewWindow.is(':checked') 49663 }); 49664 _this.ui.hideDialog(_this.$dialog); 49665 }); 49666 }); 49667 _this.ui.onDialogHidden(_this.$dialog, function () { 49668 // detach events 49669 $linkText.off(); 49670 $linkUrl.off(); 49671 $linkBtn.off(); 49672 if (deferred.state() === 'pending') { 49673 deferred.reject(); 49674 } 49675 }); 49676 _this.ui.showDialog(_this.$dialog); 49677 }).promise(); 49678 }; 49679 /** 49680 * @param {Object} layoutInfo 49681 */ 49682 LinkDialog.prototype.show = function () { 49683 var _this = this;
49684 var linkInfo = this.context.invoke('editor.getLinkInfo'); 49685 this.context.invoke('editor.saveRange'); 49686 this.showLinkDialog(linkInfo).then(function (linkInfo) { 49687 _this.context.invoke('editor.restoreRange'); 49688 _this.context.invoke('editor.createLink', linkInfo); 49689 }).fail(function () { 49690 _this.context.invoke('editor.restoreRange'); 49691 }); 49692 }; 49693 return LinkDialog; 49694 }()); 49695 49696 var LinkPopover = /** @class */ (function () { 49697 function LinkPopover(context) { 49698 var _this = this; 49699 this.context = context; 49700 this.ui = $$1.summernote.ui; 49701 this.options = context.options; 49702 this.events = { 49703 'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function () { 49704 _this.update(); 49705 }, 49706 'summernote.disable summernote.dialog.shown': function () { 49707 _this.hide(); 49708 } 49709 }; 49710 } 49711 LinkPopover.prototype.shouldInitialize = function () { 49712 return !lists.isEmpty(this.options.popover.link); 49713 }; 49714 LinkPopover.prototype.initialize = function () { 49715 this.$popover = this.ui.popover({ 49716 className: 'note-link-popover', 49717 callback: function ($node) { 49718 var $content = $node.find('.popover-content,.note-popover-content'); 49719 $content.prepend('<span><a target="_blank"></a> </span>'); 49720 } 49721 }).render().appendTo(this.options.container); 49722 var $content = this.$popover.find('.popover-content,.note-popover-content'); 49723 this.context.invoke('buttons.build', $content, this.options.popover.link); 49724 }; 49725 LinkPopover.prototype.destroy = function () { 49726 this.$popover.remove(); 49727 }; 49728 LinkPopover.prototype.update = function () { 49729 // Prevent focusing on editable when invoke('code') is executed 49730 if (!this.context.invoke('editor.hasFocus')) { 49731 this.hide(); 49732 return; 49733 } 49734 var rng = this.context.invoke('editor.getLastRange'); 49735 if (rng.isCollapsed() && rng.isOnAnchor()) { 49736 var anchor = dom.ancestor(rng.sc, dom.isAnchor); 49737 var href = $$1(anchor).attr('href'); 49738 this.$popover.find('a').attr('href', href).html(href); 49739 var pos = dom.posFromPlaceholder(anchor); 49740 this.$popover.css({ 49741 display: 'block', 49742 left: pos.left, 49743 top: pos.top 49744 }); 49745 } 49746 else { 49747 this.hide(); 49748 } 49749 }; 49750 LinkPopover.prototype.hide = function () { 49751 this.$popover.hide(); 49752 }; 49753 return LinkPopover; 49754 }()); 49755 49756 var ImageDialog = /** @class */ (function () { 49757 function ImageDialog(context) { 49758 this.context = context; 49759 this.ui = $$1.summernote.ui; 49760 this.$body = $$1(document.body); 49761 this.$editor = context.layoutInfo.editor; 49762 this.options = context.options; 49763 this.lang = this.options.langInfo; 49764 } 49765 ImageDialog.prototype.initialize = function () { 49766 var $container = this.options.dialogsInBody ? this.$body : this.$editor; 49767 var imageLimitation = ''; 49768 if (this.options.maximumImageFileSize) { 49769 var unit = Math.floor(Math.log(this.options.maximumImageFileSize) / Math.log(1024)); 49770 var readableSize = (this.options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 + 49771 ' ' + ' KMGTP'[unit] + 'B'; 49772 imageLimitation = "<small>" + (this.lang.image.maximumFileSize + ' : ' + readableSize) + "</small>"; 49773 } 49774 var body = [ 49775 '<div class="form-group note-form-group note-group-select-from-files">', 49776 '<label class="note-form-label">' + this.lang.image.selectFromFiles + '</label>', 49777 '<input class="note-image-input form-control-file note-form-control note-input" ', 49778 ' type="file" name="files" accept="image/*" multiple="multiple" />', 49779 imageLimitation, 49780 '</div>', 49781 '<div class="form-group note-group-image-url" style="overflow:auto;">', 49782 '<label class="note-form-label">' + this.lang.image.url + '</label>', 49783 '<input class="note-image-url form-control note-form-control note-input ', 49784 ' col-md-12" type="text" />', 49785 '</div>', 49786 ].join(''); 49787 var buttonClass = 'btn btn-primary note-btn note-btn-primary note-image-btn'; 49788 var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.image.insert + "\" disabled>"; 49789 this.$dialog = this.ui.dialog({ 49790 title: this.lang.image.insert, 49791 fade: this.options.dialogsFade, 49792 body: body, 49793 footer: footer 49794 }).render().appendTo($container); 49795 }; 49796 ImageDialog.prototype.destroy = function () { 49797 this.ui.hideDialog(this.$dialog); 49798 this.$dialog.remove(); 49799 }; 49800 ImageDialog.prototype.bindEnterKey = function ($input, $btn) { 49801 $input.on('keypress', function (event) { 49802 if (event.keyCode === key.code.ENTER) { 49803 event.preventDefault(); 49804 $btn.trigger('click'); 49805 } 49806 }); 49807 }; 49808 ImageDialog.prototype.show = function () { 49809 var _this = this;
49810 this.context.invoke('editor.saveRange'); 49811 this.showImageDialog().then(function (data) { 49812 // [workaround] hide dialog before restore range for IE range focus 49813 _this.ui.hideDialog(_this.$dialog); 49814 _this.context.invoke('editor.restoreRange'); 49815 if (typeof data === 'string') { // image url 49816 // If onImageLinkInsert set, 49817 if (_this.options.callbacks.onImageLinkInsert) { 49818 _this.context.triggerEvent('image.link.insert', data); 49819 } 49820 else { 49821 _this.context.invoke('editor.insertImage', data); 49822 } 49823 } 49824 else { // array of files 49825 _this.context.invoke('editor.insertImagesOrCallback', data); 49826 } 49827 }).fail(function () { 49828 _this.context.invoke('editor.restoreRange'); 49829 }); 49830 }; 49831 /** 49832 * show image dialog 49833 * 49834 * @param {jQuery} $dialog 49835 * @return {Promise} 49836 */ 49837 ImageDialog.prototype.showImageDialog = function () { 49838 var _this = this; 49839 return $$1.Deferred(function (deferred) { 49840 var $imageInput = _this.$dialog.find('.note-image-input'); 49841 var $imageUrl = _this.$dialog.find('.note-image-url'); 49842 var $imageBtn = _this.$dialog.find('.note-image-btn'); 49843 _this.ui.onDialogShown(_this.$dialog, function () { 49844 _this.context.triggerEvent('dialog.shown'); 49845 // Cloning imageInput to clear element. 49846 $imageInput.replaceWith($imageInput.clone().on('change', function (event) { 49847 deferred.resolve(event.target.files || event.target.value); 49848 }).val('')); 49849 $imageUrl.on('input paste propertychange', function () { 49850 _this.ui.toggleBtn($imageBtn, $imageUrl.val()); 49851 }).val(''); 49852 if (!env.isSupportTouch) { 49853 $imageUrl.trigger('focus'); 49854 } 49855 $imageBtn.click(function (event) { 49856 event.preventDefault(); 49857 deferred.resolve($imageUrl.val()); 49858 }); 49859 _this.bindEnterKey($imageUrl, $imageBtn); 49860 }); 49861 _this.ui.onDialogHidden(_this.$dialog, function () { 49862 $imageInput.off(); 49863 $imageUrl.off(); 49864 $imageBtn.off(); 49865 if (deferred.state() === 'pending') { 49866 deferred.reject(); 49867 } 49868 }); 49869 _this.ui.showDialog(_this.$dialog); 49870 }); 49871 }; 49872 return ImageDialog; 49873 }()); 49874 49875 /** 49876 * Image popover module 49877 * mouse events that show/hide popover will be handled by Handle.js. 49878 * Handle.js will receive the events and invoke 'imagePopover.update'. 49879 */ 49880 var ImagePopover = /** @class */ (function () { 49881 function ImagePopover(context) { 49882 var _this = this; 49883 this.context = context; 49884 this.ui = $$1.summernote.ui; 49885 this.editable = context.layoutInfo.editable[0]; 49886 this.options = context.options; 49887 this.events = { 49888 'summernote.disable': function () { 49889 _this.hide(); 49890 } 49891 }; 49892 } 49893 ImagePopover.prototype.shouldInitialize = function () { 49894 return !lists.isEmpty(this.options.popover.image); 49895 }; 49896 ImagePopover.prototype.initialize = function () { 49897 this.$popover = this.ui.popover({ 49898 className: 'note-image-popover' 49899 }).render().appendTo(this.options.container); 49900 var $content = this.$popover.find('.popover-content,.note-popover-content'); 49901 this.context.invoke('buttons.build', $content, this.options.popover.image); 49902 }; 49903 ImagePopover.prototype.destroy = function () { 49904 this.$popover.remove(); 49905 }; 49906 ImagePopover.prototype.update = function (target, event) { 49907 if (dom.isImg(target)) { 49908 var pos = dom.posFromPlaceholder(target); 49909 var posEditor = dom.posFromPlaceholder(this.editable); 49910 this.$popover.css({ 49911 display: 'block', 49912 left: this.options.popatmouse ? event.pageX - 20 : pos.left, 49913 top: this.options.popatmouse ? event.pageY -50 : Math.min(pos.top, posEditor.top) 49914 }); 49915 } 49916 else { 49917 this.hide(); 49918 } 49919 }; 49920 ImagePopover.prototype.hide = function () { 49921 this.$popover.hide(); 49922 }; 49923 return ImagePopover; 49924 }()); 49925 49926 var TablePopover = /** @class */ (function () { 49927 function TablePopover(context) { 49928 var _this = this; 49929 this.context = context; 49930 this.ui = $$1.summernote.ui; 49931 this.options = context.options; 49932 this.events = { 49933 'summernote.mousedown': function (we, e) { 49934 _this.update(e.target); 49935 }, 49936 'summernote.keyup summernote.scroll summernote.change': function () { 49937 _this.update(); 49938 }, 49939 'summernote.disable': function () { 49940 _this.hide(); 49941 } 49942 }; 49943 } 49944 TablePopover.prototype.shouldInitialize = function () { 49945 return !lists.isEmpty(this.options.popover.table); 49946 }; 49947 TablePopover.prototype.initialize = function () { 49948 this.$popover = this.ui.popover({ 49949 className: 'note-table-popover' 49950 }).render().appendTo(this.options.container); 49951 var $content = this.$popover.find('.popover-content,.note-popover-content');
49952 this.context.invoke('buttons.build', $content, this.options.popover.table); 49953 // [workaround] Disable Firefox's default table editor 49954 if (env.isFF) { 49955 document.execCommand('enableInlineTableEditing', false, false); 49956 } 49957 }; 49958 TablePopover.prototype.destroy = function () { 49959 this.$popover.remove(); 49960 }; 49961 TablePopover.prototype.update = function (target) { 49962 if (this.context.isDisabled()) { 49963 return false; 49964 } 49965 var isCell = dom.isCell(target); 49966 if (isCell) { 49967 var pos = dom.posFromPlaceholder(target); 49968 this.$popover.css({ 49969 display: 'block', 49970 left: pos.left, 49971 top: pos.top 49972 }); 49973 } 49974 else { 49975 this.hide(); 49976 } 49977 return isCell; 49978 }; 49979 TablePopover.prototype.hide = function () { 49980 this.$popover.hide(); 49981 }; 49982 return TablePopover; 49983 }()); 49984 49985 var VideoDialog = /** @class */ (function () { 49986 function VideoDialog(context) { 49987 this.context = context; 49988 this.ui = $$1.summernote.ui; 49989 this.$body = $$1(document.body); 49990 this.$editor = context.layoutInfo.editor; 49991 this.options = context.options; 49992 this.lang = this.options.langInfo; 49993 } 49994 VideoDialog.prototype.initialize = function () { 49995 var $container = this.options.dialogsInBody ? this.$body : this.$editor; 49996 var body = [ 49997 '<div class="form-group note-form-group row-fluid">', 49998 "<label class=\"note-form-label\">" + this.lang.video.url + " <small class=\"text-muted\">" + this.lang.video.providers + "</small></label>", 49999 '<input class="note-video-url form-control note-form-control note-input" type="text" />', 50000 '</div>', 50001 ].join(''); 50002 var buttonClass = 'btn btn-primary note-btn note-btn-primary note-video-btn'; 50003 var footer = "<input type=\"button\" href=\"#\" class=\"" + buttonClass + "\" value=\"" + this.lang.video.insert + "\" disabled>"; 50004 this.$dialog = this.ui.dialog({ 50005 title: this.lang.video.insert, 50006 fade: this.options.dialogsFade, 50007 body: body, 50008 footer: footer 50009 }).render().appendTo($container); 50010 }; 50011 VideoDialog.prototype.destroy = function () { 50012 this.ui.hideDialog(this.$dialog); 50013 this.$dialog.remove(); 50014 }; 50015 VideoDialog.prototype.bindEnterKey = function ($input, $btn) { 50016 $input.on('keypress', function (event) { 50017 if (event.keyCode === key.code.ENTER) { 50018 event.preventDefault(); 50019 $btn.trigger('click'); 50020 } 50021 }); 50022 }; 50023 VideoDialog.prototype.createVideoNode = function (url) { 50024 // video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm) 50025 var ytRegExp = /\/\/(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([\w|-]{11})(?:(?:[\?&]t=)(\S+))?$/; 50026 var ytRegExpForStart = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/; 50027 var ytMatch = url.match(ytRegExp); 50028 var igRegExp = /(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/; 50029 var igMatch = url.match(igRegExp); 50030 var vRegExp = /\/\/vine\.co\/v\/([a-zA-Z0-9]+)/; 50031 var vMatch = url.match(vRegExp); 50032 var vimRegExp = /\/\/(player\.)?vimeo\.com\/([a-z]*\/)*(\d+)[?]?.*/; 50033 var vimMatch = url.match(vimRegExp); 50034 var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/; 50035 var dmMatch = url.match(dmRegExp); 50036 var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/; 50037 var youkuMatch = url.match(youkuRegExp); 50038 var qqRegExp = /\/\/v\.qq\.com.*?vid=(.+)/; 50039 var qqMatch = url.match(qqRegExp); 50040 var qqRegExp2 = /\/\/v\.qq\.com\/x?\/?(page|cover).*?\/([^\/]+)\.html\??.*/; 50041 var qqMatch2 = url.match(qqRegExp2); 50042 var mp4RegExp = /^.+.(mp4|m4v)$/; 50043 var mp4Match = url.match(mp4RegExp); 50044 var oggRegExp = /^.+.(ogg|ogv)$/; 50045 var oggMatch = url.match(oggRegExp); 50046 var webmRegExp = /^.+.(webm)$/; 50047 var webmMatch = url.match(webmRegExp); 50048 var fbRegExp = /(?:www\.|\/\/)facebook\.com\/([^\/]+)\/videos\/([0-9]+)/; 50049 var fbMatch = url.match(fbRegExp); 50050 var $video; 50051 if (ytMatch && ytMatch[1].length === 11) { 50052 var youtubeId = ytMatch[1]; 50053 var start = 0; 50054 if (typeof ytMatch[2] !== 'undefined') { 50055 var ytMatchForStart = ytMatch[2].match(ytRegExpForStart); 50056 if (ytMatchForStart) { 50057 for (var n = [3600, 60, 1], i = 0, r = n.length; i < r; i++) { 50058 start += (typeof ytMatchForStart[i + 1] !== 'undefined' ? n[i] * parseInt(ytMatchForStart[i + 1], 10) : 0); 50059 } 50060 } 50061 } 50062 $video = $$1('<iframe>') 50063 .attr('frameborder', 0) 50064 .attr('src', '//www.youtube.com/embed/' + youtubeId + (start > 0 ? '?start=' + start : '')) 50065 .attr('width', '640').attr('height', '360'); 50066 } 50067 else if (igMatch && igMatch[0].length) { 50068 $video = $$1('<iframe>') 50069 .attr('frameborder', 0) 50070 .attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/') 50071 .attr('width', '612').attr('height', '710') 50072 .attr('scrolling', 'no') 50073 .attr('allowtransparency', 'true'); 50074 } 50075 else if (vMatch && vMatch[0].length) { 50076 $video = $$1('<iframe>') 50077 .attr('frameborder', 0) 50078 .attr('src', vMatch[0] + '/embed/simple') 50079 .attr('width', '600').attr('height', '600') 50080 .attr('class', 'vine-embed'); 50081 } 50082 else if (vimMatch && vimMatch[3].length) { 50083 $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>') 50084 .attr('frameborder', 0) 50085 .attr('src', '//player.vimeo.com/video/' + vimMatch[3]) 50086 .attr('width', '640').attr('height', '360'); 50087 } 50088 else if (dmMatch && dmMatch[2].length) { 50089 $video = $$1('<iframe>') 50090 .attr('frameborder', 0) 50091 .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2]) 50092 .attr('width', '640').attr('height', '360'); 50093 } 50094 else if (youkuMatch && youkuMatch[1].length) { 50095 $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>') 50096 .attr('frameborder', 0) 50097 .attr('height', '498') 50098 .attr('width', '510') 50099 .attr('src', '//player.youku.com/embed/' + youkuMatch[1]); 50100 } 50101 else if ((qqMatch && qqMatch[1].length) || (qqMatch2 && qqMatch2[2].length)) { 50102 var vid = ((qqMatch && qqMatch[1].length) ? qqMatch[1] : qqMatch2[2]); 50103 $video = $$1('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>') 50104 .attr('frameborder', 0) 50105 .attr('height', '310') 50106 .attr('width', '500') 50107 .attr('src', 'http://v.qq.com/iframe/player.html?vid=' + vid + '&auto=0'); 50108 } 50109 else if (mp4Match || oggMatch || webmMatch) { 50110 $video = $$1('<video controls>') 50111 .attr('src', url) 50112 .attr('width', '640').attr('height', '360'); 50113 } 50114 else if (fbMatch && fbMatch[0].length) { 50115 $video = $$1('<iframe>') 50116 .attr('frameborder', 0) 50117 .attr('src', 'https://www.facebook.com/plugins/video.php?href=' + encodeURIComponent(fbMatch[0]) + '&show_text=0&width=560') 50118 .attr('width', '560').attr('height', '301') 50119 .attr('scrolling', 'no') 50120 .attr('allowtransparency', 'true'); 50121 } 50122 else { 50123 // this is not a known video link. Now what, Cat? Now what? 50124 return false;
50125 } 50126 $video.addClass('note-video-clip'); 50127 return $video[0]; 50128 }; 50129 VideoDialog.prototype.show = function () { 50130 var _this = this; 50131 var text = this.context.invoke('editor.getSelectedText'); 50132 this.context.invoke('editor.saveRange'); 50133 this.showVideoDialog(text).then(function (url) { 50134 // [workaround] hide dialog before restore range for IE range focus 50135 _this.ui.hideDialog(_this.$dialog); 50136 _this.context.invoke('editor.restoreRange'); 50137 // build node 50138 var $node = _this.createVideoNode(url); 50139 if ($node) { 50140 // insert video node 50141 _this.context.invoke('editor.insertNode', $node); 50142 } 50143 }).fail(function () { 50144 _this.context.invoke('editor.restoreRange'); 50145 }); 50146 }; 50147 /** 50148 * show image dialog 50149 * 50150 * @param {jQuery} $dialog 50151 * @return {Promise} 50152 */ 50153 VideoDialog.prototype.showVideoDialog = function (text) { 50154 var _this = this; 50155 return $$1.Deferred(function (deferred) { 50156 var $videoUrl = _this.$dialog.find('.note-video-url'); 50157 var $videoBtn = _this.$dialog.find('.note-video-btn'); 50158 _this.ui.onDialogShown(_this.$dialog, function () { 50159 _this.context.triggerEvent('dialog.shown'); 50160 $videoUrl.on('input paste propertychange', function () { 50161 _this.ui.toggleBtn($videoBtn, $videoUrl.val()); 50162 }); 50163 if (!env.isSupportTouch) { 50164 $videoUrl.trigger('focus'); 50165 } 50166 $videoBtn.click(function (event) { 50167 event.preventDefault(); 50168 deferred.resolve($videoUrl.val()); 50169 }); 50170 _this.bindEnterKey($videoUrl, $videoBtn); 50171 }); 50172 _this.ui.onDialogHidden(_this.$dialog, function () { 50173 $videoUrl.off(); 50174 $videoBtn.off(); 50175 if (deferred.state() === 'pending') { 50176 deferred.reject(); 50177 } 50178 }); 50179 _this.ui.showDialog(_this.$dialog); 50180 }); 50181 }; 50182 return VideoDialog; 50183 }()); 50184 50185 var HelpDialog = /** @class */ (function () { 50186 function HelpDialog(context) { 50187 this.context = context; 50188 this.ui = $$1.summernote.ui; 50189 this.$body = $$1(document.body); 50190 this.$editor = context.layoutInfo.editor; 50191 this.options = context.options; 50192 this.lang = this.options.langInfo; 50193 } 50194 HelpDialog.prototype.initialize = function () { 50195 var $container = this.options.dialogsInBody ? this.$body : this.$editor; 50196 var body = [ 50197 '<p class="text-center">', 50198 '<a href="http://summernote.org/" target="_blank">Summernote 0.8.12</a> · ', 50199 '<a href="https://github.com/summernote/summernote" target="_blank">Project</a> · ', 50200 '<a href="https://github.com/summernote/summernote/issues" target="_blank">Issues</a>', 50201 '</p>', 50202 ].join(''); 50203 this.$dialog = this.ui.dialog({ 50204 title: this.lang.options.help, 50205 fade: this.options.dialogsFade, 50206 body: this.createShortcutList(), 50207 footer: body, 50208 callback: function ($node) { 50209 $node.find('.modal-body,.note-modal-body').css({ 50210 'max-height': 300, 50211 'overflow': 'scroll' 50212 }); 50213 } 50214 }).render().appendTo($container); 50215 }; 50216 HelpDialog.prototype.destroy = function () { 50217 this.ui.hideDialog(this.$dialog); 50218 this.$dialog.remove(); 50219 }; 50220 HelpDialog.prototype.createShortcutList = function () { 50221 var _this = this; 50222 var keyMap = this.options.keyMap[env.isMac ? 'mac' : 'pc']; 50223 return Object.keys(keyMap).map(function (key) { 50224 var command = keyMap[key]; 50225 var $row = $$1('<div><div class="help-list-item"/></div>'); 50226 $row.append($$1('<label><kbd>' + key + '</kdb></label>').css({ 50227 'width': 180, 50228 'margin-right': 10 50229 })).append($$1('<span/>').html(_this.context.memo('help.' + command) || command)); 50230 return $row.html(); 50231 }).join(''); 50232 }; 50233 /** 50234 * show help dialog 50235 * 50236 * @return {Promise} 50237 */ 50238 HelpDialog.prototype.showHelpDialog = function () { 50239 var _this = this; 50240 return $$1.Deferred(function (deferred) { 50241 _this.ui.onDialogShown(_this.$dialog, function () { 50242 _this.context.triggerEvent('dialog.shown'); 50243 deferred.resolve(); 50244 }); 50245 _this.ui.showDialog(_this.$dialog); 50246 }).promise(); 50247 }; 50248 HelpDialog.prototype.show = function () { 50249 var _this = this;
50250 this.context.invoke('editor.saveRange'); 50251 this.showHelpDialog().then(function () { 50252 _this.context.invoke('editor.restoreRange'); 50253 }); 50254 }; 50255 return HelpDialog; 50256 }()); 50257 50258 var AIR_MODE_POPOVER_X_OFFSET = 20; 50259 var AirPopover = /** @class */ (function () { 50260 function AirPopover(context) { 50261 var _this = this; 50262 this.context = context; 50263 this.ui = $$1.summernote.ui; 50264 this.options = context.options; 50265 this.events = { 50266 'summernote.keyup summernote.mouseup summernote.scroll': function () { 50267 _this.update(); 50268 }, 50269 'summernote.disable summernote.change summernote.dialog.shown': function () { 50270 _this.hide(); 50271 }, 50272 'summernote.focusout': function (we, e) { 50273 // [workaround] Firefox doesn't support relatedTarget on focusout 50274 // - Ignore hide action on focus out in FF. 50275 if (env.isFF) { 50276 return; 50277 } 50278 if (!e.relatedTarget || !dom.ancestor(e.relatedTarget, func.eq(_this.$popover[0]))) { 50279 _this.hide(); 50280 } 50281 } 50282 }; 50283 } 50284 AirPopover.prototype.shouldInitialize = function () { 50285 return this.options.airMode && !lists.isEmpty(this.options.popover.air); 50286 }; 50287 AirPopover.prototype.initialize = function () { 50288 this.$popover = this.ui.popover({ 50289 className: 'note-air-popover' 50290 }).render().appendTo(this.options.container); 50291 var $content = this.$popover.find('.popover-content'); 50292 this.context.invoke('buttons.build', $content, this.options.popover.air); 50293 }; 50294 AirPopover.prototype.destroy = function () { 50295 this.$popover.remove(); 50296 }; 50297 AirPopover.prototype.update = function () { 50298 var styleInfo = this.context.invoke('editor.currentStyle'); 50299 if (styleInfo.range && !styleInfo.range.isCollapsed()) { 50300 var rect = lists.last(styleInfo.range.getClientRects()); 50301 if (rect) { 50302 var bnd = func.rect2bnd(rect); 50303 this.$popover.css({ 50304 display: 'block', 50305 left: Math.max(bnd.left + bnd.width / 2, 0) - AIR_MODE_POPOVER_X_OFFSET, 50306 top: bnd.top + bnd.height 50307 }); 50308 this.context.invoke('buttons.updateCurrentStyle', this.$popover); 50309 } 50310 } 50311 else { 50312 this.hide(); 50313 } 50314 }; 50315 AirPopover.prototype.hide = function () { 50316 this.$popover.hide(); 50317 }; 50318 return AirPopover; 50319 }()); 50320 50321 var POPOVER_DIST = 5; 50322 var HintPopover = /** @class */ (function () { 50323 function HintPopover(context) { 50324 var _this = this; 50325 this.context = context; 50326 this.ui = $$1.summernote.ui; 50327 this.$editable = context.layoutInfo.editable; 50328 this.options = context.options; 50329 this.hint = this.options.hint || []; 50330 this.direction = this.options.hintDirection || 'bottom'; 50331 this.hints = Array.isArray(this.hint) ? this.hint : [this.hint]; 50332 this.events = { 50333 'summernote.keyup': function (we, e) { 50334 if (!e.isDefaultPrevented()) { 50335 _this.handleKeyup(e); 50336 } 50337 }, 50338 'summernote.keydown': function (we, e) { 50339 _this.handleKeydown(e); 50340 }, 50341 'summernote.disable summernote.dialog.shown': function () { 50342 _this.hide(); 50343 } 50344 }; 50345 } 50346 HintPopover.prototype.shouldInitialize = function () { 50347 return this.hints.length > 0; 50348 }; 50349 HintPopover.prototype.initialize = function () { 50350 var _this = this; 50351 this.lastWordRange = null; 50352 this.$popover = this.ui.popover({ 50353 className: 'note-hint-popover', 50354 hideArrow: true, 50355 direction: '' 50356 }).render().appendTo(this.options.container); 50357 this.$popover.hide(); 50358 this.$content = this.$popover.find('.popover-content,.note-popover-content'); 50359 this.$content.on('click', '.note-hint-item', function (e) { 50360 _this.$content.find('.active').removeClass('active'); 50361 $$1(e.currentTarget).addClass('active'); 50362 _this.replace(); 50363 }); 50364 }; 50365 HintPopover.prototype.destroy = function () { 50366 this.$popover.remove(); 50367 }; 50368 HintPopover.prototype.selectItem = function ($item) { 50369 this.$content.find('.active').removeClass('active'); 50370 $item.addClass('active'); 50371 this.$content[0].scrollTop = $item[0].offsetTop - (this.$content.innerHe
50371ight() / 2); 50372 }; 50373 HintPopover.prototype.moveDown = function () { 50374 var $current = this.$content.find('.note-hint-item.active'); 50375 var $next = $current.next(); 50376 if ($next.length) { 50377 this.selectItem($next); 50378 } 50379 else { 50380 var $nextGroup = $current.parent().next(); 50381 if (!$nextGroup.length) { 50382 $nextGroup = this.$content.find('.note-hint-group').first(); 50383 } 50384 this.selectItem($nextGroup.find('.note-hint-item').first()); 50385 } 50386 }; 50387 HintPopover.prototype.moveUp = function () { 50388 var $current = this.$content.find('.note-hint-item.active'); 50389 var $prev = $current.prev(); 50390 if ($prev.length) { 50391 this.selectItem($prev); 50392 } 50393 else { 50394 var $prevGroup = $current.parent().prev(); 50395 if (!$prevGroup.length) { 50396 $prevGroup = this.$content.find('.note-hint-group').last(); 50397 } 50398 this.selectItem($prevGroup.find('.note-hint-item').last()); 50399 } 50400 }; 50401 HintPopover.prototype.replace = function () { 50402 var $item = this.$content.find('.note-hint-item.active'); 50403 if ($item.length) { 50404 var node = this.nodeFromItem($item);
vendor: 7,303 bytes, lines 50405-50592
50405 // XXX: consider to move codes to editor for recording redo/undo. 50406 this.lastWordRange.insertNode(node); 50407 range.createFromNode(node).collapse().select(); 50408 this.lastWordRange = null; 50409 this.hide(); 50410 this.context.triggerEvent('change', this.$editable.html(), this.$editable[0]); 50411 this.context.invoke('editor.focus'); 50412 } 50413 }; 50414 HintPopover.prototype.nodeFromItem = function ($item) { 50415 var hint = this.hints[$item.data('index')]; 50416 var item = $item.data('item'); 50417 var node = hint.content ? hint.content(item) : item; 50418 if (typeof node === 'string') { 50419 node = dom.createText(node); 50420 } 50421 return node; 50422 }; 50423 HintPopover.prototype.createItemTemplates = function (hintIdx, items) { 50424 var hint = this.hints[hintIdx]; 50425 return items.map(function (item, idx) { 50426 var $item = $$1('<div class="note-hint-item"/>'); 50427 $item.append(hint.template ? hint.template(item) : item + ''); 50428 $item.data({ 50429 'index': hintIdx, 50430 'item': item 50431 }); 50432 return $item; 50433 }); 50434 }; 50435 HintPopover.prototype.handleKeydown = function (e) { 50436 if (!this.$popover.is(':visible')) { 50437 return; 50438 } 50439 if (e.keyCode === key.code.ENTER) { 50440 e.preventDefault(); 50441 this.replace(); 50442 } 50443 else if (e.keyCode === key.code.UP) { 50444 e.preventDefault(); 50445 this.moveUp(); 50446 } 50447 else if (e.keyCode === key.code.DOWN) { 50448 e.preventDefault(); 50449 this.moveDown(); 50450 } 50451 }; 50452 HintPopover.prototype.searchKeyword = function (index, keyword, callback) { 50453 var hint = this.hints[index]; 50454 if (hint && hint.match.test(keyword) && hint.search) { 50455 var matches = hint.match.exec(keyword); 50456 hint.search(matches[1], callback); 50457 } 50458 else { 50459 callback(); 50460 } 50461 }; 50462 HintPopover.prototype.createGroup = function (idx, keyword) { 50463 var _this = this; 50464 var $group = $$1('<div class="note-hint-group note-hint-group-' + idx + '"/>'); 50465 this.searchKeyword(idx, keyword, function (items) { 50466 items = items || []; 50467 if (items.length) { 50468 $group.html(_this.createItemTemplates(idx, items)); 50469 _this.show(); 50470 } 50471 }); 50472 return $group; 50473 }; 50474 HintPopover.prototype.handleKeyup = function (e) { 50475 var _this = this; 50476 if (!lists.contains([key.code.ENTER, key.code.UP, key.code.DOWN], e.keyCode)) { 50477 var wordRange = this.context.invoke('editor.getLastRange').getWordRange(); 50478 var keyword_1 = wordRange.toString(); 50479 if (this.hints.length && keyword_1) { 50480 this.$content.empty(); 50481 var bnd = func.rect2bnd(lists.last(wordRange.getClientRects())); 50482 if (bnd) { 50483 this.$popover.hide(); 50484 this.lastWordRange = wordRange; 50485 this.hints.forEach(function (hint, idx) { 50486 if (hint.match.test(keyword_1)) { 50487 _this.createGroup(idx, keyword_1).appendTo(_this.$content); 50488 } 50489 }); 50490 // select first .note-hint-item 50491 this.$content.find('.note-hint-item:first').addClass('active'); 50492 // set position for popover after group is created 50493 if (this.direction === 'top') { 50494 this.$popover.css({ 50495 left: bnd.left, 50496 top: bnd.top - this.$popover.outerHeight() - POPOVER_DIST 50497 }); 50498 } 50499 else { 50500 this.$popover.css({ 50501 left: bnd.left, 50502 top: bnd.top + bnd.height + POPOVER_DIST 50503 }); 50504 } 50505 } 50506 } 50507 else { 50508 this.hide(); 50509 } 50510 } 50511 }; 50512 HintPopover.prototype.show = function () { 50513 this.$popover.show(); 50514 }; 50515 HintPopover.prototype.hide = function () { 50516 this.$popover.hide(); 50517 }; 50518 return HintPopover; 50519 }()); 50520 50521 $$1.summernote = $$1.extend($$1.summernote, { 50522 version: '0.8.12', 50523 plugins: {}, 50524 dom: dom, 50525 range: range, 50526 options: { 50527 langInfo: $$1.summernote.lang['en-US'], 50528 modules: { 50529 'editor': Editor, 50530 'clipboard': Clipboard, 50531 'dropzone': Dropzone, 50532 'codeview': CodeView, 50533 'statusbar': Statusbar, 50534 'fullscreen': Fullscreen, 50535 'handle': Handle, 50536 // FIXME: HintPopover must be front of autolink 50537 // - Script error about range when Enter key is pressed on hint popover 50538 'hintPopover': HintPopover, 50539 'autoLink': AutoLink, 50540 'autoSync': AutoSync, 50541 'autoReplace': AutoReplace, 50542 'placeholder': Placeholder, 50543 'buttons': Buttons, 50544 'toolbar': Toolbar, 50545 'linkDialog': LinkDialog, 50546 'linkPopover': LinkPopover, 50547 'imageDialog': ImageDialog, 50548 'imagePopover': ImagePopover, 50549 'tablePopover': TablePopover, 50550 'videoDialog': VideoDialog, 50551 'helpDialog': HelpDialog, 50552 'airPopover': AirPopover 50553 }, 50554 buttons: {}, 50555 lang: 'en-US', 50556 followingToolbar: false, 50557 otherStaticBar: '', 50558 // toolbar 50559 toolbar: [ 50560 ['style', ['style']], 50561 ['font', ['bold', 'underline', 'clear']], 50562 ['fontname', ['fontname']], 50563 ['color', ['color']], 50564 ['para', ['ul', 'ol', 'paragraph']], 50565 ['table', ['table']], 50566 ['insert', ['link', 'picture', 'video']], 50567 ['view', ['fullscreen', 'codeview', 'help']], 50568 ], 50569 // popover 50570 popatmouse: true, 50571 popover: { 50572 image: [ 50573 ['resize', ['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone']], 50574 ['float', ['floatLeft', 'floatRight', 'floatNone']], 50575 ['remove', ['removeMedia']], 50576 ], 50577 link: [ 50578 ['link', ['linkDialogShow', 'unlink']], 50579 ], 50580 table: [ 50581 ['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']], 50582 ['delete', ['deleteRow', 'deleteCol', 'deleteTable']], 50583 ], 50584 air: [ 50585 ['color', ['color']], 50586 ['font', ['bold', 'underline', 'clear']], 50587 ['para', ['ul', 'paragraph']], 50588 ['table', ['table']], 50589 ['insert', ['link', 'picture']], 50590 ] 50591 }, 50592 // air mode: inline editor
50593 airMode: false, 50594 width: null, 50595 height: null, 50596 linkTargetBlank: true, 50597 focus: false, 50598 tabSize: 4, 50599 styleWithSpan: true, 50600 shortcuts: true, 50601 textareaAutoSync: true, 50602 hintDirection: 'bottom', 50603 tooltip: 'auto', 50604 container: 'body', 50605 maxTextLength: 0, 50606 blockquoteBreakingLevel: 2, 50607 spellCheck: true, 50608 styleTags: ['p', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'], 50609 fontNames: [ 50610 'Arial', 'Arial Black', 'Comic Sans MS', 'Courier New', 50611 'Helvetica Neue', 'Helvetica', 'Impact', 'Lucida Grande', 50612 'Tahoma', 'Times New Roman', 'Verdana', 50613 ], 50614 fontNamesIgnoreCheck: [], 50615 fontSizes: ['8', '9', '10', '11', '12', '14', '18', '24', '36'], 50616 // pallete colors(n x n) 50617 colors: [ 50618 ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'], 50619 ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'], 50620 ['#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE'], 50621 ['#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD'], 50622 ['#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5'], 50623 ['#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B'], 50624 ['#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842'], 50625 ['#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031'], 50626 ], 50627 // http://chir.ag/projects/name-that-color/ 50628 colorsName: [ 50629 ['Black', 'Tundora', 'Dove Gray', 'Star Dust', 'Pale Slate', 'Gallery', 'Alabaster', 'White'], 50630 ['Red', 'Orange Peel', 'Yellow', 'Green', 'Cyan', 'Blue', 'Electric Violet', 'Magenta'], 50631 ['Azalea', 'Karry', 'Egg White', 'Zanah', 'Botticelli', 'Tropical Blue', 'Mischka', 'Twilight'], 50632 ['Tonys Pink', 'Peach Orange', 'Cream Brulee', 'Sprout', 'Casper', 'Perano', 'Cold Purple', 'Careys Pink'], 50633 ['Mandy', 'Rajah', 'Dandelion', 'Olivine', 'Gulf Stream', 'Viking', 'Blue Marguerite', 'Puce'], 50634 ['Guardsman Red', 'Fire Bush', 'Golden Dream', 'Chelsea Cucumber', 'Smalt Blue', 'Boston Blue', 'Butterfly Bush', 'Cadillac'], 50635 ['Sangria', 'Mai Tai', 'Buddha Gold', 'Forest Green', 'Eden', 'Venice Blue', 'Meteorite', 'Claret'], 50636 ['Rosewood', 'Cinnamon', 'Olive', 'Parsley', 'Tiber', 'Midnight Blue', 'Valentino', 'Loulou'], 50637 ], 50638 colorButton: { 50639 foreColor: '#000000', 50640 backColor: '#FFFF00' 50641 }, 50642 lineHeights: ['1.0', '1.2', '1.4', '1.5', '1.6', '1.8', '2.0', '3.0'], 50643 tableClassName: 'table table-bordered d-table', 50644 insertTableMaxSize: { 50645 col: 10, 50646 row: 10 50647 }, 50648 dialogsInBody: false, 50649 dialogsFade: false, 50650 maximumImageFileSize: null, 50651 callbacks: { 50652 onBeforeCommand: null, 50653 onBlur: null, 50654 onBlurCodeview: null, 50655 onChange: null, 50656 onChangeCodeview: null, 50657 onDialogShown: null, 50658 onEnter: null, 50659 onFocus: null, 50660 onImageLinkInsert: null, 50661 onImageUpload: null, 50662 onImageUploadError: null, 50663 onInit: null, 50664 onKeydown: null, 50665 onKeyup: null, 50666 onMousedown: null, 50667 onMouseup: null, 50668 onPaste: null, 50669 onScroll: null 50670 }, 50671 codemirror: { 50672 mode: 'text/html', 50673 htmlMode: true, 50674 lineNumbers: true 50675 }, 50676 codeviewFilter: false, 50677 codeviewFilterRegex: /<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi, 50678 codeviewIframeFilter: true, 50679 codeviewIframeWhitelistSrc: [], 50680 codeviewIframeWhitelistSrcBase: [ 50681 'www.youtube.com', 50682 'www.youtube-nocookie.com', 50683 'www.facebook.com', 50684 'vine.co', 50685 'instagram.com', 50686 'player.vimeo.com', 50687 'www.dailymotion.com', 50688 'player.youku.com', 50689 'v.qq.com', 50690 ], 50691 keyMap: { 50692 pc: { 50693 'ENTER': 'insertParagraph', 50694 'CTRL+Z': 'undo', 50695 'CTRL+Y': 'redo', 50696 'TAB': 'tab', 50697 'SHIFT+TAB': 'untab', 50698 'CTRL+B': 'bold', 50699 'CTRL+I': 'italic', 50700 'CTRL+U': 'underline', 50701 'CTRL+SHIFT+S': 'strikethrough', 50702 'CTRL+BACKSLASH': 'removeFormat', 50703 'CTRL+SHIFT+L': 'justifyLeft', 50704 'CTRL+SHIFT+E': 'justifyCenter', 50705 'CTRL+SHIFT+R': 'justifyRight', 50706 'CTRL+SHIFT+J': 'justifyFull', 50707 'CTRL+SHIFT+NUM7': 'insertUnorderedList', 50708 'CTRL+SHIFT+NUM8': 'insertOrderedList', 50709 'CTRL+LEFTBRACKET': 'outdent', 50710 'CTRL+RIGHTBRACKET': 'indent', 50711 'CTRL+NUM0': 'formatPara', 50712 'CTRL+NUM1': 'formatH1', 50713 'CTRL+NUM2': 'formatH2', 50714 'CTRL+NUM3': 'formatH3', 50715 'CTRL+NUM4': 'formatH4', 50716 'CTRL+NUM5': 'formatH5', 50717 'CTRL+NUM6': 'formatH6', 50718 'CTRL+ENTER': 'insertHorizontalRule', 50719 'CTRL+K': 'linkDialog.show' 50720 }, 50721 mac: { 50722 'ENTER': 'insertParagraph', 50723 'CMD+Z': 'undo', 50724 'CMD+SHIFT+Z': 'redo', 50725 'TAB': 'tab', 50726 'SHIFT+TAB': 'untab', 50727 'CMD+B': 'bold', 50728 'CMD+I': 'italic', 50729 'CMD+U': 'underline', 50730 'CMD+SHIFT+S': 'strikethrough', 50731 'CMD+BACKSLASH': 'removeFormat', 50732 'CMD+SHIFT+L': 'justifyLeft', 50733 'CMD+SHIFT+E': 'justifyCenter', 50734 'CMD+SHIFT+R': 'justifyRight', 50735 'CMD+SHIFT+J': 'justifyFull', 50736 'CMD+SHIFT+NUM7': 'insertUnorderedList', 50737 'CMD+SHIFT+NUM8': 'insertOrderedList', 50738 'CMD+LEFTBRACKET': 'outdent', 50739 'CMD+RIGHTBRACKET': 'indent', 50740 'CMD+NUM0': 'formatPara', 50741 'CMD+NUM1': 'formatH1', 50742 'CMD+NUM2': 'formatH2', 50743 'CMD+NUM3': 'formatH3', 50744 'CMD+NUM4': 'formatH4', 50745 'CMD+NUM5': 'formatH5', 50746 'CMD+NUM6': 'formatH6', 50747 'CMD+ENTER': 'insertHorizontalRule', 50748 'CMD+K': 'linkDialog.show' 50749 } 50750 }, 50751 icons: { 50752 'align': 'note-icon-align', 50753 'alignCenter': 'note-icon-align-center', 50754 'alignJustify': 'note-icon-align-justify', 50755 'alignLeft': 'note-icon-align-left', 50756 'alignRight': 'note-icon-align-right', 50757 'rowBelow': 'note-icon-row-below', 50758 'colBefore': 'note-icon-col-before',
50759 'colAfter': 'note-icon-col-after', 50760 'rowAbove': 'note-icon-row-above', 50761 'rowRemove': 'note-icon-row-remove', 50762 'colRemove': 'note-icon-col-remove', 50763 'indent': 'note-icon-align-indent', 50764 'outdent': 'note-icon-align-outdent', 50765 'arrowsAlt': 'note-icon-arrows-alt', 50766 'bold': 'note-icon-bold', 50767 'caret': 'note-icon-caret', 50768 'circle': 'note-icon-circle', 50769 'close': 'note-icon-close', 50770 'code': 'note-icon-code', 50771 'eraser': 'note-icon-eraser', 50772 'floatLeft': 'note-icon-float-left', 50773 'floatRight': 'note-icon-float-right', 50774 'font': 'note-icon-font', 50775 'frame': 'note-icon-frame', 50776 'italic': 'note-icon-italic', 50777 'link': 'note-icon-link', 50778 'unlink': 'note-icon-chain-broken', 50779 'magic': 'note-icon-magic', 50780 'menuCheck': 'note-icon-menu-check', 50781 'minus': 'note-icon-minus', 50782 'orderedlist': 'note-icon-orderedlist', 50783 'pencil': 'note-icon-pencil', 50784 'picture': 'note-icon-picture', 50785 'question': 'note-icon-question', 50786 'redo': 'note-icon-redo', 50787 'rollback': 'note-icon-rollback', 50788 'square': 'note-icon-square', 50789 'strikethrough': 'note-icon-strikethrough', 50790 'subscript': 'note-icon-subscript', 50791 'superscript': 'note-icon-superscript', 50792 'table': 'note-icon-table', 50793 'textHeight': 'note-icon-text-height', 50794 'trash': 'note-icon-trash', 50795 'underline': 'note-icon-underline', 50796 'undo': 'note-icon-undo', 50797 'unorderedlist': 'note-icon-unorderedlist', 50798 'video': 'note-icon-video' 50799 } 50800 } 50801 }); 50802 50803 $$1.summernote = $$1.extend($$1.summernote, { 50804 ui: ui 50805 }); 50806 50807})); 50808//# sourceMappingURL=summernote.js.map 50809 50810 50811 50812(function(factory){ 50813 if(typeof define==='function'&&define.amd){ 50814 define(['jquery'],factory); 50815 }else if(typeof module==='object'&&module.exports){ 50816 module.exports=factory(require('jquery')); 50817 }else{ 50818 factory(window.jQuery); 50819 } 50820}(function($){ 50821 $.extend(true,$.summernote.lang,{ 50822 'en-US':{ 50823 imageAttributes:{ 50824 tooltip:'Image Attributes', 50825 pluginImageTitle:'Image Attributes', 50826 pluginLinkTitle:'Link Attributes', 50827 title:'Title', 50828 alt:'Alt', 50829 class:'Class', 50830 style:'Style', 50831 href:'URL', 50832 target:'Target', 50833 linkClass:'Link Class', 50834 rel:'Link Rel', 50835 relBlank:'Do not use Rel Attribute', 50836 relAlternate:'Alternate: Links to an alternate version of the document', 50837 relAuthor:'Author: Links to the Author of the Document', 50838 relBookmark:'Bookmark: Permanent URL used for Bookmarking', 50839 relHelp:'Help: Links to a Help Document', 50840 relLicense:'License: Links to copyright information for the document', 50841 relNext:'Next: The next document in a selection', 50842 relNofollow:'NoFollow: Links to an unendorsed document, like a paid link, also stops Search Engines following this link', 50843 relNoreferrer:'NoReferrer: Specifies that the browser should not send a HTTP Header', 50844 relPrefetch:'PreFetch: Specifies that the target document should be cached', 50845 relPrev:'Prev: The previous document in a selection', 50846 relSearch:'Search: Links to a search tool for the document', 50847 relTag:'Tag: A tag (Keyword) for the current documentNext' 50848 } 50849 } 50850 }); 50851 $.extend($.summernote.options,{ 50852 imageAttributes:{ 50853 icon:'<i class="fa fa-edit"></i>', // This Icon is from the LibreICONS class Extras and SVG Icons for Summernote. 50854 removeEmpty:true 50855 } 50856 }) 50857 $.extend($.summernote.plugins,{ 50858 'imageAttributes':function(context){ 50859 var self=this; 50860 var ui=$.summernote.ui; 50861 var $note=context.layoutInfo.note; 50862 var $editor=context.layoutInfo.editor; 50863 var $editable=context.layoutInfo.editable; 50864 var options=context.options; 50865 var lang=options.langInfo; 50866 context.memo('button.imageAttributes',function(){ 50867 var button=ui.button({ 50868 contents:options.imageAttributes.icon, 50869 tooltip:lang.imageAttributes.tooltip, 50870 click:function(e){
50871 context.invoke('imageAttributes.show'); 50872 } 50873 }); 50874 return button.render(); 50875 }); 50876 this.initialize=function(){ 50877 var $container=options.dialogsInBody?$(document.body):$editor; 50878 var body='<h5 class="d-none">'+lang.imageAttributes.pluginImageTitle+'</h5>'+ 50879 '<div class="form-group d-none">'+ 50880 '<label class="control-label col-xs-2">'+lang.imageAttributes.title+'</label>'+ 50881 '<div class="input-group col-xs-10">'+ 50882 '<input type="text" class="note-image-attributes-title form-control">'+ 50883 '</div>'+ 50884 '</div>'+ 50885 '<div class="form-group d-none">'+ 50886 '<label class="control-label col-xs-2">'+lang.imageAttributes.alt+'</label>'+ 50887 '<div class="input-group col-xs-10">'+ 50888 '<input type="text" class="note-image-attributes-alt form-control">'+ 50889 '</div>'+ 50890 '</div>'+ 50891 '<div class="form-group d-none">'+ 50892 '<label class="control-label col-xs-2">'+lang.imageAttributes.class+'</label>'+ 50893 '<div class="input-group col-xs-10">'+ 50894 '<input type="text" class="note-image-attributes-class form-control">'+ 50895 '<div class="input-group-btn">'+ 50896 '<select class="note-image-attributes-class-select btn btn-default" onchange="$(\'.note-image-attributes-class\').val($(\'.note-image-attributes-class\').val()+\' \'+$(this).val());">'+ 50897 '<option value="">Select Class</option>'+ 50898 '<option value="img-responsive">Responsive</option>'+ 50899 '<option value="img-rounded">Rounded</option>'+ 50900 '<option value="img-circle">Circle</option>'+ 50901 '<option value="img-thumbnail">Thumbnail</option>'+ 50902 '</select>'+ 50903 '</div>'+ 50904 '</div>'+ 50905 '</div>'+ 50906 '<div class="form-group d-none">'+ 50907 '<label class="control-label col-xs-2">'+lang.imageAttributes.style + '</label>'+ 50908 '<div class="input-group col-xs-10">'+ 50909 '<input type="text" class="note-image-attributes-style form-control">'+ 50910 '</div>'+ 50911 '</div>'+ 50912 '<h5 class="d-none">'+lang.imageAttributes.pluginLinkTitle+'</h5>'+ 50913 '<div class="form-group">'+ 50914 '<label class="control-label col-xs-2">'+lang.imageAttributes.href+'</label>'+ 50915 '<div class="input-group col-xs-10">'+ 50916 '<input type="text" class="note-image-attributes-href form-control" name="href">'+ 50917 '</div>'+ 50918 '</div>'+ 50919 '<div class="form-group">'+ 50920 '<label class="control-label col-xs-2">'+lang.imageAttributes.target+'</label>'+ 50921 '<div class="input-group col-xs-10">'+ 50922 '<select class="note-image-attributes-target form-control" name="target">'+ 50923 '<option value="_self">Self</option>'+ 50924 '<option value="_blank">Blank</option>'+ 50925 '<option value="_top">Top</option>'+ 50926 '<option value="_parent">Parent</option>'+ 50927 '</select>'+ 50928 '</div>'+ 50929 '</div>'+ 50930 '<div class="form-group d-none">'+ 50931 '<label class="control-label col-xs-2">'+lang.imageAttributes.linkClass+'</label>'+ 50932 '<div class="input-group col-xs-10">'+ 50933 '<input type="text" class="note-image-attributes-link-class form-control" name="linkClass">'+ 50934 '</div>'+ 50935 '</div>'+ 50936 '<div class="form-group d-none">'+ 50937 '<label class="control-label col-xs-2">'+lang.imageAttributes.rel+'</label>'+ 50938 '<div class="input-group col-xs-10">'+ 50939 '<select class="note-image-attributes-link-rel form-control" name="linkRel">'+ 50940 '<option value="">'+lang.imageAttributes.relBlank+'</option>'+ 50941 '<option value="alternate">'+lang.imageAttributes.relAlternate+'</option>'+ 50942 '<option value="author">'+lang.imageAttributes.relAuthor+'</option>'+ 50943 '<option value="bookmark">'+lang.imageAttributes.relBookmark+'</option>'+ 50944 '<option value="help">'+lang.imageAttributes.relHelp+'</option>'+ 50945 '<option value="license">'+lang.imageAttributes.relLicense+'</option>'+ 50946 '<option value="next">'+lang.imageAttributes.relNext+'</option>'+ 50947 '<option value="nofollow">'+lang.imageAttributes.relNofollow+'</option>'+ 50948 '<option value="noreferrer">'+lang.imageAttributes.relNoreferrer+'</option>'+ 50949 '<option value="prefetch">'+lang.imageAttributes.relPrefetch+'</option>'+ 50950 '<option value="prev">'+lang.imageAttributes.relPrev+'</option>'+ 50951 '<option value="search">'+lang.imageAttributes.relSearch+'</option>'+ 50952 '<option value="tag">'+lang.imageAttributes.relTag+'</option>'+ 50953 '</select>'+ 50954 '</div>'+ 50955 '</div>'; 50956 this.$dialog=ui.dialog({ 50957 title:'Image Attributes', 50958 body:body, 50959 footer:'<button href="#" class="btn btn-primary note-image-attributes-btn">OK</button>' 50960 }).render().appendTo($container); 50961 }; 50962 this.destroy=function(){ 50963 ui.hideDialog(this.$dialog); 50964 this.$dialog.remove(); 50965 }; 50966 this.bindEnterKey=function($input,$btn){ 50967 $input.on('keypress',function(event){ 50968 if(event.keyCode===13){ 50969 $btn.trigger('click'); 50970 } 50971 }); 50972 }; 50973 this.show=function(){ 50974 var $img=$($editable.data('target')); 50975 var imgInfo={ 50976 imgDom:$img, 50977 title:$img.attr('title'), 50978 alt:$img.attr('alt'), 50979 class:$img.attr('class'), 50980 style:$img.attr('style'), 50981 imgLink:$($img.context).parent().is("a")?$($img.context).parent():null 50982 }; 50983 this.showLinkDialog(imgInfo) 50984 .then(function(imgInfo){ 50985 ui.hideDialog(self.$dialog); 50986 var $img=imgInfo.imgDom; 50987 if(options.imageAttributes.removeEmpty){ 50988 if(imgInfo.alt){ 50989 $img.attr('alt',imgInfo.alt); 50990 }else{ 50991 $img.removeAttr('alt'); 50992 } 50993 if(imgInfo.title){ 50994 $img.attr('title',imgInfo.title); 50995 }else{ 50996 $img.removeAttr('title'); 50997 } 50998 if(imgInfo.class){ 50999 $img.attr('class',imgInfo.class); 51000 }else{ 51001 $img.removeAttr('class'); 51002 } 51003 if(imgInfo.style){ 51004 $img.attr('style',imgInfo.style); 51005 }else{ 51006 $img.removeAttr('style'); 51007 } 51008 }else{ 51009 $img.attr('alt',imgInfo.alt); 51010 $img.attr('title',imgInfo.title); 51011 $img.attr('class',imgInfo.class); 51012 $img.attr('style',imgInfo.style); 51013 } 51014 if($img.parent().is("a")){ 51015 $img.unwrap(); 51016 } 51017 var hrefRegex=new RegExp(/(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/gi); 51018 if(imgInfo.href.match(hrefRegex)){ 51019 var lnktxt='<a'; 51020 if(imgInfo.linkClass){ 51021 lnktxt+=' class="'+imgInfo.linkClass+'"'; 51022 } 51023 lnktxt+=' href="'+imgInfo.href+'"'; 51024 lnktxt+=' target="'+imgInfo.target+'"'; 51025 if(imgInfo.linkRel){ 51026 lnktxt+=' ref="'+imgInfo.linkRel+'"'; 51027 } 51028 lnktxt+='></a>'; 51029 $img.wrap(lnktxt); 51030 } 51031 $note.val(context.invoke('code')); 51032 $note.change(); 51033 }); 51034 }; 51035 this.showLinkDialog=function(imgInfo){ 51036 return $.Deferred(function(deferred){ 51037 var $imageTitle=self.$dialog.find('.note-image-attributes-title'), 51038 $imageAlt=self.$dialog.find('.note-image-attributes-alt'), 51039 $imageClass=self.$dialog.find('.note-image-attributes-class'),
51040 $imageStyle=self.$dialog.find('.note-image-attributes-style'), 51041 $linkHref=self.$dialog.find('.note-image-attributes-href'), 51042 $linkTarget=self.$dialog.find('.note-image-attributes-target'), 51043 $linkClass=self.$dialog.find('.note-image-attributes-link-class'), 51044 $linkRel=self.$dialog.find('.note-image-attributes-link-rel'), 51045 $editBtn=self.$dialog.find('.note-image-attributes-btn'); 51046 if(imgInfo.imgLink){ 51047 $linkHref.val(imgInfo.imgLink.attr('href')); 51048 $linkClass.val(imgInfo.imgLink.attr('class')); 51049 $linkTarget.find('option').each(function(){ 51050 if($(this).val()==imgInfo.imgLink.attr('target')){ 51051 $(this).attr('selected','selected'); 51052 } 51053 }); 51054 $linkRel.find('option').each(function(){ 51055 if($(this).val()==imgInfo.imgLink.attr('rel')){ 51056 $(this).attr('selected','selected'); 51057 } 51058 }); 51059 } 51060 ui.onDialogShown(self.$dialog,function(){ 51061 context.triggerEvent('dialog.shown'); 51062 $editBtn.click(function(e){ 51063 e.preventDefault(); 51064 deferred.resolve({ 51065 imgDom:imgInfo.imgDom, 51066 title:$imageTitle.val(), 51067 alt:$imageAlt.val(), 51068 class:$imageClass.val(), 51069 style:$imageStyle.val(), 51070 href:$linkHref.val(), 51071 target:$linkTarget.val(), 51072 linkClass:$linkClass.val(), 51073 linkRel:$linkRel.val() 51074 }); 51075 }); 51076 $imageTitle.val(imgInfo.title).focus; 51077 $imageAlt.val(imgInfo.alt); 51078 $imageClass.val(imgInfo.class); 51079 $imageStyle.val(imgInfo.style); 51080 self.bindEnterKey( 51081 $editBtn 51082 ); 51083 }); 51084 ui.onDialogHidden(self.$dialog,function(){ 51085 $editBtn.off('click'); 51086 if(deferred.state()==='pending'){ 51087 deferred.reject(); 51088 } 51089 }); 51090 ui.showDialog(self.$dialog); 51091 }); 51092 }; 51093 } 51094 }); 51095})); 51096 51097 51098 51099 51100 51101// Released under MIT license 51102// Copyright (c) 2009-2010 Dominic Baggott 51103// Copyright (c) 2009-2010 Ash Berlin 51104// Copyright (c) 2011 Christoph Dorn <[email protected]> (http://www.christophdorn.com) 51105 51106/*jshint browser:true, devel:true */ 51107 51108(function( expose ) { 51109 51110/** 51111 * class Markdown 51112 * 51113 * Markdown processing in Javascript done right. We have very particular views 51114 * on what constitutes 'right' which include: 51115 * 51116 * - produces well-formed HTML (this means that em and strong nesting is 51117 * important) 51118 * 51119 * - has an intermediate representation to allow processing of parsed data (We 51120 * in fact have two, both as [JsonML]: a markdown tree and an HTML tree). 51121 * 51122 * - is easily extensible to add new dialects without having to rewrite the 51123 * entire parsing mechanics 51124 * 51125 * - has a good test suite 51126 * 51127 * This implementation fulfills all of these (except that the test suite could 51128 * do with expanding to automatically run all the fixtures from other Markdown 51129 * implementations.) 51130 * 51131 * ##### Intermediate Representation 51132 * 51133 * *TODO* Talk about this :) Its JsonML, but document the node names we use. 51134 * 51135 * [JsonML]: http://jsonml.org/ "JSON Markup Language" 51136 **/ 51137var Markdown = expose.Markdown = function(dialect) { 51138 switch (typeof dialect) { 51139 case "undefined": 51140 this.dialect = Markdown.dialects.Gruber; 51141 break; 51142 case "object": 51143 this.dialect = dialect; 51144 break; 51145 default: 51146 if ( dialect in Markdown.dialects ) { 51147 this.dialect = Markdown.dialects[dialect]; 51148 } 51149 else { 51150 throw new Error("Unknown Markdown dialect '" + String(dialect) + "'"); 51151 } 51152 break; 51153 } 51154 this.em_state = []; 51155 this.strong_state = []; 51156 this.debug_indent = ""; 51157}; 51158 51159/** 51160 * parse( markdown, [dialect] ) -> JsonML 51161 * - markdown (String): markdown string to parse 51162 * - dialect (String | Dialect): the dialect to use, defaults to gruber 51163 * 51164 * Parse `markdown` and return a markdown document as a Markdown.JsonML tree. 51165 **/ 51166expose.parse = function( source, dialect ) { 51167 // dialect will default if undefined 51168 var md = new Markdown( dialect ); 51169 return md.toTree( source ); 51170}; 51171 51172/** 51173 * toHTML( markdown, [dialect] ) -> String 51174 * toHTML( md_tree ) -> String 51175 * - markdown (String): markdown string to parse 51176 * - md_tree (Markdown.JsonML): parsed markdown tree 51177 * 51178 * Take markdown (either as a string or as a JsonML tree) and run it through 51179 * [[toHTMLTree]] then turn it into a well-formated HTML fragment. 51180 **/ 51181expose.toHTML = function toHTML( source , dialect , options ) { 51182 var input = expose.toHTMLTree( source , dialect , options ); 51183 51184 return expose.renderJsonML( input ); 51185}; 51186 51187/** 51188 * toHTMLTree( markdown, [dialect] ) -> JsonML 51189 * toHTMLTree( md_tree ) -> JsonML 51190 * - markdown (String): markdown string to parse 51191 * - dialect (String | Dialect): the dialect to use, defaults to gruber 51192 * - md_tree (Markdown.JsonML): parsed markdown tree 51193 * 51194 * Turn markdown into HTML, represented as a JsonML tree. If a string is given 51195 * to this function, it is first parsed into a markdown tree by calling 51196 * [[parse]]. 51197 **/ 51198expose.toHTMLTree = function toHTMLTree( input, dialect , options ) { 51199 // convert string input to an MD tree 51200 if ( typeof input ==="string" ) input = this.parse( input, dialect ); 51201 51202 // Now convert the MD tree to an HTML tree 51203 51204 // remove references from the tree 51205 var attrs = extract_attr( input ), 51206 refs = {}; 51207 51208 if ( attrs && attrs.references ) { 51209 refs = attrs.references; 51210 } 51211 51212 var html = convert_tree_to_html( input, refs , options ); 51213 merge_text_nodes( html ); 51214 return html; 51215}; 51216 51217// For Spidermonkey based engines 51218function mk_block_toSource() { 51219 return "Markdown.mk_block( " + 51220 uneval(this.toString()) + 51221 ", " + 51222 uneval(this.trailing) + 51223 ", " + 51224 uneval(this.lineNumber) + 51225 " )"; 51226} 51227 51228// node 51229function mk_block_inspect() { 51230 var util = require("util"); 51231 return "Markdown.mk_block( " + 51232 util.inspect(this.toString()) + 51233 ", " + 51234 util.inspect(this.trailing) + 51235 ", " + 51236 util.inspect(this.lineNumber) + 51237 " )"; 51238 51239} 51240 51241var mk_block = Markdown.mk_block = function(block, trail, line) { 51242 // Be helpful for default case in tests. 51243 if ( arguments.length == 1 ) trail = "\n\n"; 51244 51245 var s = new String(block); 51246 s.trailing = trail; 51247 // To make it clear its not just a string 51248 s.inspect = mk_block_inspect; 51249 s.toSource = mk_block_toSource; 51250 51251 if ( line != undefined ) 51252 s.lineNumber = line; 51253 51254 return s; 51255}; 51256 51257function count_lines( str ) { 51258 var n = 0, i = -1; 51259 while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++; 51260 return n; 51261} 51262 51263// Internal - split source into rough blocks 51264Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) { 51265 input = input.replace(/(\r\n|\n|\r)/g, "\n"); 51266 // [\s\S] matches _anything_ (newline or space) 51267 // [^] is equivalent but doesn't work in IEs.
51268 var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g, 51269 blocks = [], 51270 m; 51271 51272 var line_no = 1; 51273 51274 if ( ( m = /^(\s*\n)/.exec(input) ) != null ) { 51275 // skip (but count) leading blank lines 51276 line_no += count_lines( m[0] ); 51277 re.lastIndex = m[0].length; 51278 } 51279 51280 while ( ( m = re.exec(input) ) !== null ) { 51281 if (m[2] == "\n#") { 51282 m[2] = "\n"; 51283 re.lastIndex--; 51284 } 51285 blocks.push( mk_block( m[1], m[2], line_no ) ); 51286 line_no += count_lines( m[0] ); 51287 } 51288 51289 return blocks; 51290}; 51291 51292/** 51293 * Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ] 51294 * - block (String): the block to process 51295 * - next (Array): the following blocks 51296 * 51297 * Process `block` and return an array of JsonML nodes representing `block`. 51298 * 51299 * It does this by asking each block level function in the dialect to process 51300 * the block until one can. Succesful handling is indicated by returning an 51301 * array (with zero or more JsonML nodes), failure by a false value. 51302 * 51303 * Blocks handlers are responsible for calling [[Markdown#processInline]] 51304 * themselves as appropriate. 51305 * 51306 * If the blocks were split incorrectly or adjacent blocks need collapsing you 51307 * can adjust `next` in place using shift/splice etc. 51308 * 51309 * If any of this default behaviour is not right for the dialect, you can 51310 * define a `__call__` method on the dialect that will get invoked to handle 51311 * the block processing. 51312 */ 51313Markdown.prototype.processBlock = function processBlock( block, next ) { 51314 var cbs = this.dialect.block, 51315 ord = cbs.__order__; 51316 51317 if ( "__call__" in cbs ) { 51318 return cbs.__call__.call(this, block, next); 51319 } 51320 51321 for ( var i = 0; i < ord.length; i++ ) { 51322 //D:this.debug( "Testing", ord[i] ); 51323 var res = cbs[ ord[i] ].call( this, block, next ); 51324 if ( res ) { 51325 //D:this.debug(" matched"); 51326 if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) ) 51327 this.debug(ord[i], "didn't return a proper array"); 51328 //D:this.debug( "" ); 51329 return res; 51330 } 51331 } 51332 51333 // Uhoh! no match! Should we throw an error? 51334 return []; 51335}; 51336 51337Markdown.prototype.processInline = function processInline( block ) { 51338 return this.dialect.inline.__call__.call( this, String( block ) ); 51339}; 51340 51341/** 51342 * Markdown#toTree( source ) -> JsonML 51343 * - source (String): markdown source to parse 51344 * 51345 * Parse `source` into a JsonML tree representing the markdown document. 51346 **/ 51347// custom_tree means set this.tree to `custom_tree` and restore old value on return 51348Markdown.prototype.toTree = function toTree( source, custom_root ) { 51349 var blocks = source instanceof Array ? source : this.split_blocks( source ); 51350 51351 // Make tree a member variable so its easier to mess with in extensions 51352 var old_tree = this.tree; 51353 try { 51354 this.tree = custom_root || this.tree || [ "markdown" ]; 51355 51356 blocks: 51357 while ( blocks.length ) { 51358 var b = this.processBlock( blocks.shift(), blocks ); 51359 51360 // Reference blocks and the like won't return any content 51361 if ( !b.length ) continue blocks; 51362 51363 this.tree.push.apply( this.tree, b ); 51364 } 51365 return this.tree; 51366 } 51367 finally { 51368 if ( custom_root ) { 51369 this.tree = old_tree; 51370 } 51371 } 51372}; 51373 51374// Noop by default 51375Markdown.prototype.debug = function () { 51376 var args = Array.prototype.slice.call( arguments); 51377 args.unshift(this.debug_indent); 51378 if ( typeof print !== "undefined" ) 51379 print.apply( print, args ); 51380 if ( typeof console !== "undefined" && typeof console.log !== "undefined" ) 51381 console.log.apply( null, args ); 51382} 51383 51384Markdown.prototype.loop_re_over_block = function( re, block, cb ) { 51385 // Dont use /g regexps with this 51386 var m, 51387 b = block.valueOf(); 51388 51389 while ( b.length && (m = re.exec(b) ) != null ) { 51390 b = b.substr( m[0].length ); 51391 cb.call(this, m); 51392 } 51393 return b; 51394}; 51395 51396/** 51397 * Markdown.dialects 51398 * 51399 * Namespace of built-in dialects. 51400 **/ 51401Markdown.dialects = {}; 51402 51403/** 51404 * Markdown.dialects.Gruber 51405 * 51406 * The default dialect that follows the rules set out by John Gruber's 51407 * markdown.pl as closely as possible. Well actually we follow the behaviour of 51408 * that script which in some places is not exactly what the syntax web page 51409 * says. 51410 **/ 51411Markdown.dialects.Gruber = { 51412 block: { 51413 atxHeader: function atxHeader( block, next ) { 51414 var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ ); 51415 51416 if ( !m ) return undefined; 51417 51418 var header = [ "header", { level: m[ 1 ].length } ]; 51419 Array.prototype.push.apply(header, this.processInline(m[ 2 ])); 51420 51421 if ( m[0].length < block.length ) 51422 next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) ); 51423 51424 return [ header ]; 51425 }, 51426 51427 setextHeader: function setextHeader( block, next ) { 51428 var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ ); 51429 51430 if ( !m ) return undefined; 51431 51432 var level = ( m[ 2 ] === "=" ) ? 1 : 2; 51433 var header = [ "header", { level : level }, m[ 1 ] ]; 51434 51435 if ( m[0].length < block.length ) 51436 next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) ); 51437 51438 return [ header ]; 51439 }, 51440 51441 code: function code( block, next ) { 51442 // | Foo 51443 // |bar 51444 // should be a code block followed by a paragraph. Fun 51445 // 51446 // There might also be adjacent code block to merge. 51447 51448 var ret = [], 51449 re = /^(?: {0,3}\t| {4})(.*)\n?/, 51450 lines; 51451 51452 // 4 spaces + content 51453 if ( !block.match( re ) ) return undefined; 51454 51455 block_search: 51456 do { 51457 // Now pull out the rest of the lines 51458 var b = this.loop_re_over_block(
51459 re, block.valueOf(), function( m ) { ret.push( m[1] ); } ); 51460 51461 if ( b.length ) { 51462 // Case alluded to in first comment. push it back on as a new block 51463 next.unshift( mk_block(b, block.trailing) ); 51464 break block_search; 51465 } 51466 else if ( next.length ) { 51467 // Check the next block - it might be code too 51468 if ( !next[0].match( re ) ) break block_search; 51469 51470 // Pull how how many blanks lines follow - minus two to account for .join 51471 ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) ); 51472 51473 block = next.shift(); 51474 } 51475 else { 51476 break block_search; 51477 } 51478 } while ( true ); 51479 51480 return [ [ "code_block", ret.join("\n") ] ]; 51481 }, 51482 51483 horizRule: function horizRule( block, next ) { 51484 // this needs to find any hr in the block to handle abutting blocks 51485 var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ ); 51486 51487 if ( !m ) { 51488 return undefined; 51489 } 51490 51491 var jsonml = [ [ "hr" ] ]; 51492 51493 // if there's a leading abutting block, process it 51494 if ( m[ 1 ] ) { 51495 jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) ); 51496 } 51497 51498 // if there's a trailing abutting block, stick it into next 51499 if ( m[ 3 ] ) { 51500 next.unshift( mk_block( m[ 3 ] ) ); 51501 } 51502 51503 return jsonml; 51504 }, 51505 51506 // There are two types of lists. Tight and loose. Tight lists have no whitespace 51507 // between the items (and result in text just in the <li>) and loose lists, 51508 // which have an empty line between list items, resulting in (one or more) 51509 // paragraphs inside the <li>. 51510 // 51511 // There are all sorts weird edge cases about the original markdown.pl's 51512 // handling of lists: 51513 // 51514 // * Nested lists are supposed to be indented by four chars per level. But 51515 // if they aren't, you can get a nested list by indenting by less than 51516 // four so long as the indent doesn't match an indent of an existing list 51517 // item in the 'nest stack'. 51518 // 51519 // * The type of the list (bullet or number) is controlled just by the 51520 // first item at the indent. Subsequent changes are ignored unless they 51521 // are for nested lists 51522 // 51523 lists: (function( ) { 51524 // Use a closure to hide a few variables. 51525 var any_list = "[*+-]|\\d+\\.", 51526 bullet_list = /[*+-]/, 51527 number_list = /\d+\./, 51528 // Capture leading indent as it matters for determining nested lists. 51529 is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ), 51530 indent_re = "(?: {0,3}\\t| {4})"; 51531 51532 // TODO: Cache this regexp for certain depths. 51533 // Create a regexp suitable for matching an li for a given stack depth 51534 function regex_for_depth( depth ) { 51535 51536 return new RegExp( 51537 // m[1] = indent, m[2] = list_type 51538 "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" + 51539 // m[3] = cont 51540 "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})" 51541 ); 51542 } 51543 function expand_tab( input ) { 51544 return input.replace( / {0,3}\t/g, " " ); 51545 } 51546 51547 // Add inline content `inline` to `li`. inline comes from processInline 51548 // so is an array of content 51549 function add(li, loose, inline, nl) { 51550 if ( loose ) { 51551 li.push( [ "para" ].concat(inline) ); 51552 return; 51553 } 51554 // Hmmm, should this be any block level element or just paras? 51555 var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para" 51556 ? li[li.length -1] 51557 : li; 51558 51559 // If there is already some content in this list, add the new line in 51560 if ( nl && li.length > 1 ) inline.unshift(nl); 51561 51562 for ( var i = 0; i < inline.length; i++ ) { 51563 var what = inline[i], 51564 is_str = typeof what == "string"; 51565 if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) { 51566 add_to[ add_to.length-1 ] += what; 51567 } 51568 else { 51569 add_to.push( what ); 51570 } 51571 } 51572 } 51573 51574 // contained means have an indent greater than the current one. On 51575 // *every* line in the block 51576 function get_contained_blocks( depth, blocks ) { 51577 51578 var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ), 51579 replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"), 51580 ret = []; 51581 51582 while ( blocks.length > 0 ) { 51583 if ( re.exec( blocks[0] ) ) { 51584 var b = blocks.shift(), 51585 // Now remove that indent 51586 x = b.replace( replace, ""); 51587
51588 ret.push( mk_block( x, b.trailing, b.lineNumber ) ); 51589 } 51590 else { 51591 break; 51592 } 51593 } 51594 return ret; 51595 } 51596 51597 // passed to stack.forEach to turn list items up the stack into paras 51598 function paragraphify(s, i, stack) { 51599 var list = s.list; 51600 var last_li = list[list.length-1]; 51601 51602 if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) { 51603 return; 51604 } 51605 if ( i + 1 == stack.length ) { 51606 // Last stack frame 51607 // Keep the same array, but replace the contents 51608 last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) ); 51609 } 51610 else { 51611 var sublist = last_li.pop(); 51612 last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist ); 51613 } 51614 } 51615 51616 // The matcher function 51617 return function( block, next ) { 51618 var m = block.match( is_list_re ); 51619 if ( !m ) return undefined; 51620 51621 function make_list( m ) { 51622 var list = bullet_list.exec( m[2] ) 51623 ? ["bulletlist"] 51624 : ["numberlist"]; 51625 51626 stack.push( { list: list, indent: m[1] } ); 51627 return list; 51628 } 51629 51630 51631 var stack = [], // Stack of lists for nesting. 51632 list = make_list( m ), 51633 last_li, 51634 loose = false, 51635 ret = [ stack[0].list ], 51636 i; 51637 51638 // Loop to search over block looking for inner block elements and loose lists 51639 loose_search: 51640 while ( true ) { 51641 // Split into lines preserving new lines at end of line 51642 var lines = block.split( /(?=\n)/ ); 51643 51644 // We have to grab all lines for a li and call processInline on them 51645 // once as there are some inline things that can span lines. 51646 var li_accumulate = ""; 51647 51648 // Loop over the lines in this block looking for tight lists. 51649 tight_search: 51650 for ( var line_no = 0; line_no < lines.length; line_no++ ) { 51651 var nl = "", 51652 l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; }); 51653 51654 // TODO: really should cache this 51655 var line_re = regex_for_depth( stack.length ); 51656 51657 m = l.match( line_re ); 51658 //print( "line:", uneval(l), "\nline match:", uneval(m) ); 51659 51660 // We have a list item 51661 if ( m[1] !== undefined ) { 51662 // Process the previous list item, if any 51663 if ( li_accumulate.length ) { 51664 add( last_li, loose, this.processInline( li_accumulate ), nl ); 51665 // Loose mode will have been dealt with. Reset it 51666 loose = false; 51667 li_accumulate = ""; 51668 } 51669 51670 m[1] = expand_tab( m[1] ); 51671 var wanted_depth = Math.floor(m[1].length/4)+1; 51672 //print( "want:", wanted_depth, "stack:", stack.length); 51673 if ( wanted_depth > stack.length ) { 51674 // Deep enough for a nested list outright 51675 //print ( "new nested list" ); 51676 list = make_list( m ); 51677 last_li.push( list ); 51678 last_li = list[1] = [ "listitem" ]; 51679 } 51680 else { 51681 // We aren't deep enough to be strictly a new level. This is 51682 // where Md.pl goes nuts. If the indent matches a level in the 51683 // stack, put it there, else put it one deeper then the 51684 // wanted_depth deserves. 51685 var found = false; 51686 for ( i = 0; i < stack.length; i++ ) { 51687 if ( stack[ i ].indent != m[1] ) continue; 51688 list = stack[ i ].list; 51689 stack.splice( i+1, stack.length - (i+1) ); 51690 found = true; 51691 break; 51692 } 51693 51694 if (!found) { 51695 //print("not found. l:", uneval(l)); 51696 wanted_depth++; 51697 if ( wanted_depth <= stack.length ) { 51698 stack.splice(wanted_depth, stack.length - wanted_depth); 51699 //print("Desired depth now", wanted_depth, "stack:", stack.length); 51700 list = stack[wanted_depth-1].list; 51701 //print("list:", uneval(list) ); 51702 } 51703 else { 51704 //print ("made new stack for messy indent"); 51705 list = make_list(m); 51706 last_li.push(list); 51707 } 51708 } 51709 51710 //print( uneval(list), "last", list === stack[stack.length-1].list ); 51711 last_li = [ "listitem" ]; 51712 list.push(last_li); 51713 } // end depth of shenegains 51714 nl = ""; 51715 } 51716 51717 // Add content 51718 if ( l.length > m[0].length ) { 51719 li_accumulate += nl + l.substr( m[0].length ); 51720 } 51721 } // tight_search 51722 51723 if ( li_accumulate.length ) { 51724 add( last_li, loose, this.processInline( li_accumulate ), nl ); 51725 // Loose mode will have been dealt with. Reset it 51726 loose = false;
51727 li_accumulate = ""; 51728 } 51729 51730 // Look at the next block - we might have a loose list. Or an extra 51731 // paragraph for the current li 51732 var contained = get_contained_blocks( stack.length, next ); 51733 51734 // Deal with code blocks or properly nested lists 51735 if ( contained.length > 0 ) { 51736 // Make sure all listitems up the stack are paragraphs 51737 forEach( stack, paragraphify, this); 51738 51739 last_li.push.apply( last_li, this.toTree( contained, [] ) ); 51740 } 51741 51742 var next_block = next[0] && next[0].valueOf() || ""; 51743 51744 if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) { 51745 block = next.shift(); 51746 51747 // Check for an HR following a list: features/lists/hr_abutting 51748 var hr = this.dialect.block.horizRule( block, next ); 51749 51750 if ( hr ) { 51751 ret.push.apply(ret, hr); 51752 break; 51753 } 51754 51755 // Make sure all listitems up the stack are paragraphs 51756 forEach( stack, paragraphify, this); 51757 51758 loose = true; 51759 continue loose_search; 51760 } 51761 break; 51762 } // loose_search 51763 51764 return ret; 51765 }; 51766 })(), 51767 51768 blockquote: function blockquote( block, next ) { 51769 if ( !block.match( /^>/m ) ) 51770 return undefined; 51771 51772 var jsonml = []; 51773 51774 // separate out the leading abutting block, if any. I.e. in this case: 51775 // 51776 // a 51777 // > b 51778 // 51779 if ( block[ 0 ] != ">" ) { 51780 var lines = block.split( /\n/ ), 51781 prev = [], 51782 line_no = block.lineNumber; 51783 51784 // keep shifting lines until you find a crotchet 51785 while ( lines.length && lines[ 0 ][ 0 ] != ">" ) { 51786 prev.push( lines.shift() ); 51787 line_no++; 51788 } 51789 51790 var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber ); 51791 jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) ); 51792 // reassemble new block of just block quotes! 51793 block = mk_block( lines.join( "\n" ), block.trailing, line_no ); 51794 } 51795 51796 51797 // if the next block is also a blockquote merge it in 51798 while ( next.length && next[ 0 ][ 0 ] == ">" ) { 51799 var b = next.shift(); 51800 block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber ); 51801 } 51802 51803 // Strip off the leading "> " and re-process as a block. 51804 var input = block.replace( /^> ?/gm, "" ), 51805 old_tree = this.tree, 51806 processedBlock = this.toTree( input, [ "blockquote" ] ), 51807 attr = extract_attr( processedBlock ); 51808 51809 // If any link references were found get rid of them 51810 if ( attr && attr.references ) { 51811 delete attr.references; 51812 // And then remove the attribute object if it's empty 51813 if ( isEmpty( attr ) ) { 51814 processedBlock.splice( 1, 1 ); 51815 } 51816 } 51817 51818 jsonml.push( processedBlock ); 51819 return jsonml; 51820 }, 51821 51822 referenceDefn: function referenceDefn( block, next) { 51823 var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/; 51824 // interesting matches are [ , ref_id, url, , title, title ] 51825 51826 if ( !block.match(re) ) 51827 return undefined; 51828 51829 // make an attribute node if it doesn't exist 51830 if ( !extract_attr( this.tree ) ) { 51831 this.tree.splice( 1, 0, {} ); 51832 } 51833 51834 var attrs = extract_attr( this.tree ); 51835 51836 // make a references hash if it doesn't exist 51837 if ( attrs.references === undefined ) { 51838 attrs.references = {}; 51839 } 51840 51841 var b = this.loop_re_over_block(re, block, function( m ) { 51842 51843 if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" ) 51844 m[2] = m[2].substring( 1, m[2].length - 1 ); 51845 51846 var ref = attrs.references[ m[1].toLowerCase() ] = { 51847 href: m[2] 51848 }; 51849 51850 if ( m[4] !== undefined ) 51851 ref.title = m[4]; 51852 else if ( m[5] !== undefined ) 51853 ref.title = m[5]; 51854 51855 } ); 51856 51857 if ( b.length ) 51858 next.unshift( mk_block( b, block.trailing ) ); 51859 51860 return []; 51861 }, 51862 51863 para: function para( block, next ) { 51864 // everything's a para! 51865 return [ ["para"].concat( this.processInline( block ) ) ]; 51866 } 51867 } 51868}; 51869 51870Markdown.dialects.Gruber.inline = { 51871 51872 __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) { 51873 var m, 51874 res, 51875 lastIndex = 0; 51876 51877 patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__; 51878 var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" ); 51879 51880 m = re.exec( text ); 51881 if (!m) { 51882 // Just boring text 51883 return [ text.length, text ]; 51884 } 51885 else if ( m[1] ) { 51886 // Some un-interesting text matched. Return that first 51887 return [ m[1].length, m[1] ]; 51888 } 51889 51890 var res; 51891 if ( m[2] in this.dialect.inline ) { 51892 res = this.dialect.inline[ m[2] ].call( 51893 this, 51894 text.substr( m.index ), m, previous_nodes || [] ); 51895 } 51896 // Default for now to make dev easier. just slurp special and output it. 51897 res = res || [ m[2].length, m[2] ]; 51898 return res; 51899 }, 51900 51901 __call__: function inline( text, patterns ) { 51902 51903 var out = [], 51904 res; 51905 51906 function add(x) { 51907 //D:self.debug(" adding output", uneval(x)); 51908 if ( typeof x == "string" && typeof out[out.length-1] == "string" ) 51909 out[ out.length-1 ] += x; 51910 else 51911 out.push(x); 51912 } 51913 51914 while ( text.length > 0 ) { 51915 res = this.dialect.inline.__oneElement__.call(this, text, patterns, out ); 51916 text = text.substr( res.shift() );
51917 forEach(res, add ) 51918 } 51919 51920 return out; 51921 }, 51922 51923 // These characters are intersting elsewhere, so have rules for them so that 51924 // chunks of plain text blocks don't include them 51925 "]": function () {}, 51926 "}": function () {}, 51927 51928 __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/, 51929 51930 "\\": function escaped( text ) { 51931 // [ length of input processed, node/children to add... ] 51932 // Only esacape: \ ` * _ { } [ ] ( ) # * + - . ! 51933 if ( this.dialect.inline.__escape__.exec( text ) ) 51934 return [ 2, text.charAt( 1 ) ]; 51935 else 51936 // Not an esacpe 51937 return [ 1, "\\" ]; 51938 }, 51939 51940 " 51946 // 1 2 3 4 <--- captures 51947 var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ ); 51948 51949 if ( m ) { 51950 if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" ) 51951 m[2] = m[2].substring( 1, m[2].length - 1 ); 51952 51953 m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0]; 51954 51955 var attrs = { alt: m[1], href: m[2] || "" }; 51956 if ( m[4] !== undefined) 51957 attrs.title = m[4]; 51958 51959 return [ m[0].length, [ "img", attrs ] ]; 51960 } 51961 51962 // ![Alt text][id] 51963 m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ ); 51964 51965 if ( m ) { 51966 // We can't check if the reference is known here as it likely wont be 51967 // found till after. Check it in md tree->hmtl tree conversion 51968 return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ]; 51969 } 51970 51971 // Just consume the '![' 51972 return [ 2, "![" ]; 51973 }, 51974 51975 "[": function link( text ) { 51976 51977 var orig = String(text); 51978 // Inline content is possible inside `link text` 51979 var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" ); 51980 51981 // No closing ']' found. Just consume the [ 51982 if ( !res ) return [ 1, "[" ]; 51983 51984 var consumed = 1 + res[ 0 ], 51985 children = res[ 1 ], 51986 link, 51987 attrs; 51988 51989 // At this point the first [...] has been parsed. See what follows to find 51990 // out which kind of link we are (reference or direct url) 51991 text = text.substr( consumed ); 51992 51993 // [link text](/path/to/img.jpg "Optional title") 51994 // 1 2 3 <--- captures 51995 // This will capture up to the last paren in the block. We then pull 51996 // back based on if there a matching ones in the url 51997 // ([here](/url/(test)) 51998 // The parens have to be balanced 51999 var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ ); 52000 if ( m ) { 52001 var url = m[1]; 52002 consumed += m[0].length; 52003 52004 if ( url && url[0] == "<" && url[url.length-1] == ">" ) 52005 url = url.substring( 1, url.length - 1 ); 52006 52007 // If there is a title we don't have to worry about parens in the url 52008 if ( !m[3] ) { 52009 var open_parens = 1; // One open that isn't in the capture 52010 for ( var len = 0; len < url.length; len++ ) { 52011 switch ( url[len] ) { 52012 case "(": 52013 open_parens++; 52014 break; 52015 case ")": 52016 if ( --open_parens == 0) { 52017 consumed -= url.length - len; 52018 url = url.substring(0, len); 52019 } 52020 break; 52021 } 52022 } 52023 } 52024 52025 // Process escapes only 52026 url = this.dialect.inline.__call__.call( this, url, /\\/ )[0]; 52027 52028 attrs = { href: url || "" }; 52029 if ( m[3] !== undefined) 52030 attrs.title = m[3]; 52031 52032 link = [ "link", attrs ].concat( children ); 52033 return [ consumed, link ]; 52034 } 52035 52036 // [Alt text][id] 52037 // [Alt text] [id] 52038 m = text.match( /^\s*\[(.*?)\]/ ); 52039 52040 if ( m ) { 52041 52042 consumed += m[ 0 ].length; 52043 52044 // [links][] uses links as its reference 52045 attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(), original: orig.substr( 0, consumed ) }; 52046 52047 link = [ "link_ref", attrs ].concat( children ); 52048 52049 // We can't check if the reference is known here as it likely wont be 52050 // found till after. Check it in md tree->hmtl tree conversion. 52051 // Store the original so that conversion can revert if the ref isn't found. 52052 return [ consumed, link ]; 52053 } 52054 52055 // [id] 52056 // Only if id is plain (no formatting.) 52057 if ( children.length == 1 && typeof children[0] == "string" ) { 52058 52059 attrs = { ref: children[0].toLowerCase(), original: orig.substr( 0, consumed ) }; 52060 link = [ "link_ref", attrs, children[0] ]; 52061 return [ consumed, link ]; 52062 } 52063 52064 // Just consume the "[" 52065 return [ 1, "[" ]; 52066 }, 52067 52068 52069 "<": function autoLink( text ) { 52070 var m; 52071 52072 if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) { 52073 if ( m[3] ) { 52074 return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ]; 52075 52076 } 52077 else if ( m[2] == "mailto" ) { 52078 return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ]; 52079 } 52080 else 52081 return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ]; 52082 } 52083 52084 return [ 1, "<" ]; 52085 }, 52086 52087 "`": function inlineCode( text ) { 52088 // Inline code block. as many backticks as you like to start it 52089 // Always skip over the opening ticks.
52090 var m = text.match( /(`+)(([\s\S]*?)\1)/ ); 52091 52092 if ( m && m[2] ) 52093 return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ]; 52094 else { 52095 // TODO: No matching end code found - warn! 52096 return [ 1, "`" ]; 52097 } 52098 }, 52099 52100 " \n": function lineBreak( text ) { 52101 return [ 3, [ "linebreak" ] ]; 52102 } 52103 52104}; 52105 52106// Meta Helper/generator method for em and strong handling 52107function strong_em( tag, md ) { 52108 52109 var state_slot = tag + "_state", 52110 other_slot = tag == "strong" ? "em_state" : "strong_state"; 52111 52112 function CloseTag(len) { 52113 this.len_after = len; 52114 this.name = "close_" + md; 52115 } 52116 52117 return function ( text, orig_match ) { 52118 52119 if ( this[state_slot][0] == md ) { 52120 // Most recent em is of this type 52121 //D:this.debug("closing", md); 52122 this[state_slot].shift(); 52123 52124 // "Consume" everything to go back to the recrusion in the else-block below 52125 return[ text.length, new CloseTag(text.length-md.length) ]; 52126 } 52127 else { 52128 // Store a clone of the em/strong states 52129 var other = this[other_slot].slice(), 52130 state = this[state_slot].slice(); 52131 52132 this[state_slot].unshift(md); 52133 52134 //D:this.debug_indent += " "; 52135 52136 // Recurse 52137 var res = this.processInline( text.substr( md.length ) ); 52138 //D:this.debug_indent = this.debug_indent.substr(2); 52139 52140 var last = res[res.length - 1]; 52141 52142 //D:this.debug("processInline from", tag + ": ", uneval( res ) ); 52143 52144 var check = this[state_slot].shift(); 52145 if ( last instanceof CloseTag ) { 52146 res.pop(); 52147 // We matched! Huzzah. 52148 var consumed = text.length - last.len_after; 52149 return [ consumed, [ tag ].concat(res) ]; 52150 } 52151 else { 52152 // Restore the state of the other kind. We might have mistakenly closed it. 52153 this[other_slot] = other; 52154 this[state_slot] = state; 52155 52156 // We can't reuse the processed result as it could have wrong parsing contexts in it. 52157 return [ md.length, md ]; 52158 } 52159 } 52160 }; // End returned function 52161} 52162 52163Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**"); 52164Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__"); 52165Markdown.dialects.Gruber.inline["*"] = strong_em("em", "*"); 52166Markdown.dialects.Gruber.inline["_"] = strong_em("em", "_"); 52167 52168 52169// Build default order from insertion order. 52170Markdown.buildBlockOrder = function(d) { 52171 var ord = []; 52172 for ( var i in d ) { 52173 if ( i == "__order__" || i == "__call__" ) continue; 52174 ord.push( i ); 52175 } 52176 d.__order__ = ord; 52177}; 52178 52179// Build patterns for inline matcher 52180Markdown.buildInlinePatterns = function(d) { 52181 var patterns = []; 52182 52183 for ( var i in d ) { 52184 // __foo__ is reserved and not a pattern 52185 if ( i.match( /^__.*__$/) ) continue; 52186 var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" ) 52187 .replace( /\n/, "\\n" ); 52188 patterns.push( i.length == 1 ? l : "(?:" + l + ")" ); 52189 } 52190 52191 patterns = patterns.join("|"); 52192 d.__patterns__ = patterns; 52193 //print("patterns:", uneval( patterns ) ); 52194 52195 var fn = d.__call__; 52196 d.__call__ = function(text, pattern) { 52197 if ( pattern != undefined ) { 52198 return fn.call(this, text, pattern); 52199 } 52200 else 52201 { 52202 return fn.call(this, text, patterns); 52203 } 52204 }; 52205}; 52206 52207Markdown.DialectHelpers = {}; 52208Markdown.DialectHelpers.inline_until_char = function( text, want ) { 52209 var consumed = 0, 52210 nodes = []; 52211 52212 while ( true ) { 52213 if ( text.charAt( consumed ) == want ) { 52214 // Found the character we were looking for 52215 consumed++; 52216 return [ consumed, nodes ]; 52217 } 52218 52219 if ( consumed >= text.length ) { 52220 // No closing char found. Abort. 52221 return null; 52222 } 52223 52224 var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) ); 52225 consumed += res[ 0 ]; 52226 // Add any returned nodes. 52227 nodes.push.apply( nodes, res.slice( 1 ) ); 52228 } 52229} 52230 52231// Helper function to make sub-classing a dialect easier 52232Markdown.subclassDialect = function( d ) { 52233 function Block() {} 52234 Block.prototype = d.block; 52235 function Inline() {} 52236 Inline.prototype = d.inline; 52237 52238 return { block: new Block(), inline: new Inline() }; 52239}; 52240 52241Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block ); 52242Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline ); 52243 52244Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber ); 52245 52246Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) { 52247 var meta = split_meta_hash( meta_string ), 52248 attr = {}; 52249 52250 for ( var i = 0; i < meta.length; ++i ) { 52251 // id: #foo 52252 if ( /^#/.test( meta[ i ] ) ) { 52253 attr.id = meta[ i ].substring( 1 ); 52254 } 52255 // class: .foo 52256 else if ( /^\./.test( meta[ i ] ) ) { 52257 // if class already exists, append the new one 52258 if ( attr["class"] ) { 52259 attr["class"] = attr["class"] + meta[ i ].replace( /./, " " ); 52260 } 52261 else { 52262 attr["class"] = meta[ i ].substring( 1 ); 52263 } 52264 } 52265 // attribute: foo=bar 52266 else if ( /\=/.test( meta[ i ] ) ) { 52267 var s = meta[ i ].split( /\=/ ); 52268 attr[ s[ 0 ] ] = s[ 1 ]; 52269 } 52270 } 52271 52272 return attr; 52273} 52274 52275function split_meta_hash( meta_string ) { 52276 var meta = meta_string.split( "" ), 52277 parts = [ "" ], 52278 in_quotes = false;
52279 52280 while ( meta.length ) { 52281 var letter = meta.shift(); 52282 switch ( letter ) { 52283 case " " : 52284 // if we're in a quoted section, keep it 52285 if ( in_quotes ) { 52286 parts[ parts.length - 1 ] += letter; 52287 } 52288 // otherwise make a new part 52289 else { 52290 parts.push( "" ); 52291 } 52292 break; 52293 case "'" : 52294 case '"' : 52295 // reverse the quotes and move straight on 52296 in_quotes = !in_quotes; 52297 break; 52298 case "\\" : 52299 // shift off the next letter to be used straight away. 52300 // it was escaped so we'll keep it whatever it is 52301 letter = meta.shift(); 52302 default : 52303 parts[ parts.length - 1 ] += letter; 52304 break; 52305 } 52306 } 52307 52308 return parts; 52309} 52310 52311Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) { 52312 // we're only interested in the first block 52313 if ( block.lineNumber > 1 ) return undefined; 52314 52315 // document_meta blocks consist of one or more lines of `Key: Value\n` 52316 if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined; 52317 52318 // make an attribute node if it doesn't exist 52319 if ( !extract_attr( this.tree ) ) { 52320 this.tree.splice( 1, 0, {} ); 52321 } 52322 52323 var pairs = block.split( /\n/ ); 52324 for ( p in pairs ) { 52325 var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ), 52326 key = m[ 1 ].toLowerCase(), 52327 value = m[ 2 ]; 52328 52329 this.tree[ 1 ][ key ] = value; 52330 } 52331 52332 // document_meta produces no content! 52333 return []; 52334}; 52335 52336Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) { 52337 // check if the last line of the block is an meta hash 52338 var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ ); 52339 if ( !m ) return undefined; 52340 52341 // process the meta hash 52342 var attr = this.dialect.processMetaHash( m[ 2 ] ); 52343 52344 var hash; 52345 52346 // if we matched ^ then we need to apply meta to the previous block 52347 if ( m[ 1 ] === "" ) { 52348 var node = this.tree[ this.tree.length - 1 ]; 52349 hash = extract_attr( node ); 52350 52351 // if the node is a string (rather than JsonML), bail 52352 if ( typeof node === "string" ) return undefined; 52353 52354 // create the attribute hash if it doesn't exist 52355 if ( !hash ) { 52356 hash = {}; 52357 node.splice( 1, 0, hash ); 52358 } 52359 52360 // add the attributes in 52361 for ( a in attr ) { 52362 hash[ a ] = attr[ a ]; 52363 } 52364 52365 // return nothing so the meta hash is removed 52366 return []; 52367 } 52368 52369 // pull the meta hash off the block and process what's left 52370 var b = block.replace( /\n.*$/, "" ), 52371 result = this.processBlock( b, [] ); 52372 52373 // get or make the attributes hash 52374 hash = extract_attr( result[ 0 ] ); 52375 if ( !hash ) { 52376 hash = {}; 52377 result[ 0 ].splice( 1, 0, hash ); 52378 } 52379 52380 // attach the attributes to the block 52381 for ( a in attr ) { 52382 hash[ a ] = attr[ a ]; 52383 } 52384 52385 return result; 52386}; 52387 52388Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) { 52389 // one or more terms followed by one or more definitions, in a single block 52390 var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/, 52391 list = [ "dl" ], 52392 i, m; 52393 52394 // see if we're dealing with a tight or loose block 52395 if ( ( m = block.match( tight ) ) ) { 52396 // pull subsequent tight DL blocks out of `next` 52397 var blocks = [ block ]; 52398 while ( next.length && tight.exec( next[ 0 ] ) ) { 52399 blocks.push( next.shift() ); 52400 } 52401 52402 for ( var b = 0; b < blocks.length; ++b ) { 52403 var m = blocks[ b ].match( tight ), 52404 terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ), 52405 defns = m[ 2 ].split( /\n:\s+/ ); 52406 52407 // print( uneval( m ) ); 52408 52409 for ( i = 0; i < terms.length; ++i ) { 52410 list.push( [ "dt", terms[ i ] ] ); 52411 } 52412 52413 for ( i = 0; i < defns.length; ++i ) { 52414 // run inline processing over the definition 52415 list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) ); 52416 } 52417 } 52418 } 52419 else { 52420 return undefined; 52421 } 52422 52423 return [ list ]; 52424}; 52425 52426// splits on unescaped instances of @ch. If @ch is not a character the result 52427// can be unpredictable 52428 52429Markdown.dialects.Maruku.block.table = function table (block, next) { 52430 52431 var _split_on_unescaped = function(s, ch) { 52432 ch = ch || '\\s'; 52433 if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; } 52434 var res = [ ], 52435 r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'), 52436 m; 52437 while(m = s.match(r)) { 52438 res.push(m[1]); 52439 s = m[2]; 52440 } 52441 res.push(s); 52442 return res; 52443 } 52444 52445 var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/, 52446 // find at least an unescaped pipe in each line 52447 no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/, 52448 i, m; 52449 if (m = block.match(leading_pipe)) { 52450 // remove leading pipes in contents 52451 // (header and horizontal rule already have the leading pipe left out) 52452 m[3] = m[3].replace(/^\s*\|/gm, ''); 52453 } else if (! ( m = block.match(no_leading_pipe))) { 52454 return undefined; 52455 } 52456 52457 var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ]; 52458 52459 // remove trailing pipes, then split on pipes 52460 // (no escaped pipes are allowed in horizontal rule) 52461 m[2] = m[2].replace(/\|\s*$/, '').split('|'); 52462 52463 // process alignment 52464 var html_attrs = [ ];
52465 forEach (m[2], function (s) { 52466 if (s.match(/^\s*-+:\s*$/)) html_attrs.push({align: "right"}); 52467 else if (s.match(/^\s*:-+\s*$/)) html_attrs.push({align: "left"}); 52468 else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"}); 52469 else html_attrs.push({}); 52470 }); 52471 52472 // now for the header, avoid escaped pipes 52473 m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|'); 52474 for (i = 0; i < m[1].length; i++) { 52475 table[1][1].push(['th', html_attrs[i] || {}].concat( 52476 this.processInline(m[1][i].trim()))); 52477 } 52478 52479 // now for body contents 52480 forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) { 52481 var html_row = ['tr']; 52482 row = _split_on_unescaped(row, '|'); 52483 for (i = 0; i < row.length; i++) { 52484 html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim()))); 52485 } 52486 table[2].push(html_row); 52487 }, this); 52488 52489 return [table]; 52490} 52491 52492Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) { 52493 if ( !out.length ) { 52494 return [ 2, "{:" ]; 52495 } 52496 52497 // get the preceeding element 52498 var before = out[ out.length - 1 ]; 52499 52500 if ( typeof before === "string" ) { 52501 return [ 2, "{:" ]; 52502 } 52503 52504 // match a meta hash 52505 var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ ); 52506 52507 // no match, false alarm 52508 if ( !m ) { 52509 return [ 2, "{:" ]; 52510 } 52511 52512 // attach the attributes to the preceeding element 52513 var meta = this.dialect.processMetaHash( m[ 1 ] ), 52514 attr = extract_attr( before ); 52515 52516 if ( !attr ) { 52517 attr = {}; 52518 before.splice( 1, 0, attr ); 52519 } 52520 52521 for ( var k in meta ) { 52522 attr[ k ] = meta[ k ]; 52523 } 52524 52525 // cut out the string and replace it with nothing 52526 return [ m[ 0 ].length, "" ]; 52527}; 52528 52529Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/; 52530 52531Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block ); 52532Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline ); 52533 52534var isArray = Array.isArray || function(obj) { 52535 return Object.prototype.toString.call(obj) == "[object Array]"; 52536}; 52537 52538var forEach; 52539// Don't mess with Array.prototype. Its not friendly 52540if ( Array.prototype.forEach ) { 52541 forEach = function( arr, cb, thisp ) { 52542 return arr.forEach( cb, thisp ); 52543 }; 52544} 52545else { 52546 forEach = function(arr, cb, thisp) { 52547 for (var i = 0; i < arr.length; i++) { 52548 cb.call(thisp || arr, arr[i], i, arr); 52549 } 52550 } 52551} 52552 52553var isEmpty = function( obj ) { 52554 for ( var key in obj ) { 52555 if ( hasOwnProperty.call( obj, key ) ) { 52556 return false; 52557 } 52558 } 52559 52560 return true; 52561} 52562 52563function extract_attr( jsonml ) { 52564 return isArray(jsonml) 52565 && jsonml.length > 1 52566 && typeof jsonml[ 1 ] === "object" 52567 && !( isArray(jsonml[ 1 ]) ) 52568 ? jsonml[ 1 ] 52569 : undefined; 52570} 52571 52572 52573 52574/** 52575 * renderJsonML( jsonml[, options] ) -> String 52576 * - jsonml (Array): JsonML array to render to XML 52577 * - options (Object): options 52578 * 52579 * Converts the given JsonML into well-formed XML. 52580 * 52581 * The options currently understood are: 52582 * 52583 * - root (Boolean): wether or not the root node should be included in the 52584 * output, or just its children. The default `false` is to not include the 52585 * root itself. 52586 */ 52587expose.renderJsonML = function( jsonml, options ) { 52588 options = options || {}; 52589 // include the root element in the rendered output? 52590 options.root = options.root || false; 52591 52592 var content = []; 52593 52594 if ( options.root ) { 52595 content.push( render_tree( jsonml ) ); 52596 } 52597 else { 52598 jsonml.shift(); // get rid of the tag 52599 if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) { 52600 jsonml.shift(); // get rid of the attributes 52601 } 52602 52603 while ( jsonml.length ) { 52604 content.push( render_tree( jsonml.shift() ) ); 52605 } 52606 } 52607 52608 return content.join( "\n\n" ); 52609}; 52610 52611function escapeHTML( text ) { 52612 return text.replace( /&/g, "&" ) 52613 .replace( /</g, "<" ) 52614 .replace( />/g, ">" ) 52615 .replace( /"/g, """ ) 52616 .replace( /'/g, "'" ); 52617} 52618 52619function render_tree( jsonml ) { 52620 // basic case 52621 if ( typeof jsonml === "string" ) { 52622 return escapeHTML( jsonml ); 52623 } 52624 52625 var tag = jsonml.shift(), 52626 attributes = {}, 52627 content = []; 52628 52629 if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) { 52630 attributes = jsonml.shift(); 52631 } 52632 52633 while ( jsonml.length ) { 52634 content.push( render_tree( jsonml.shift() ) ); 52635 } 52636 52637 var tag_attrs = ""; 52638 for ( var a in attributes ) { 52639 tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"'; 52640 } 52641 52642 // be careful about adding whitespace here for inline elements 52643 if ( tag == "img" || tag == "br" || tag == "hr" ) { 52644 return "<"+ tag + tag_attrs + "/>"; 52645 } 52646 else { 52647 return "<"+ tag + tag_attrs + ">" + content.join( "" ) + "</" + tag + ">"; 52648 } 52649} 52650 52651function convert_tree_to_html( tree, references, options ) { 52652 var i; 52653 options = options || {}; 52654 52655 // shallow clone 52656 var jsonml = tree.slice( 0 ); 52657 52658 if ( typeof options.preprocessTreeNode === "function" ) { 52659 jsonml = options.preprocessTreeNode(jsonml, references); 52660 } 52661 52662 // Clone attributes if they exist 52663 var attrs = extract_attr( jsonml ); 52664 if ( attrs ) { 52665 jsonml[ 1 ] = {}; 52666 for ( i in attrs ) { 52667 jsonml[ 1 ][ i ] = attrs[ i ]; 52668 } 52669 attrs = jsonml[ 1 ]; 52670 } 52671 52672 // basic case 52673 if ( typeof jsonml === "string" ) { 52674 return jsonml; 52675 } 52676 52677 // convert this node 52678 switch ( jsonml[ 0 ] ) { 52679 case "header": 52680 jsonml[ 0 ] = "h" + jsonml[ 1 ].level; 52681 delete jsonml[ 1 ].level; 52682 break; 52683 case "bulletlist": 52684 jsonml[ 0 ] = "ul"; 52685 break; 52686 case "numberlist": 52687 jsonml[ 0 ] = "ol"; 52688 break; 52689 case "listitem": 52690 jsonml[ 0 ] = "li"; 52691 break; 52692 case "para": 52693 jsonml[ 0 ] = "p"; 52694 break; 52695 case "markdown": 52696 jsonml[ 0 ] = "html"; 52697 if ( attrs ) delete attrs.references; 52698 break; 52699 case "code_block": 52700 jsonml[ 0 ] = "pre"; 52701 i = attrs ? 2 : 1; 52702 var code = [ "code" ]; 52703 code.push.apply( code, jsonml.splice( i, jsonml.length - i ) ); 52704 jsonml[ i ] = code; 52705 break; 52706 case "inlinecode": 52707 jsonml[ 0 ] = "code"; 52708 break; 52709 case "img": 52710 jsonml[ 1 ].src = jsonml[ 1 ].href; 52711 delete jsonml[ 1 ].href; 52712 break; 52713 case "linebreak": 52714 jsonml[ 0 ] = "br"; 52715 break; 52716 case "link": 52717 jsonml[ 0 ] = "a"; 52718 break; 52719 case "link_ref": 52720 jsonml[ 0 ] = "a"; 52721 52722 // grab this ref and clean up the attribute node 52723 var ref = references[ attrs.ref ]; 52724 52725 // if the reference exists, make the link 52726 if ( ref ) { 52727 delete attrs.ref; 52728 52729 // add in the href and title, if present 52730 attrs.href = ref.href; 52731 if ( ref.title ) { 52732 attrs.title = ref.title; 52733 } 52734 52735 // get rid of the unneeded original text 52736 delete attrs.original; 52737 } 52738 // the reference doesn't exist, so revert to plain text 52739 else { 52740 return attrs.original; 52741 } 52742 break; 52743 case "img_ref": 52744 jsonml[ 0 ] = "img"; 52745 52746 // grab this ref and clean up the attribute node 52747 var ref = references[ attrs.ref ]; 52748 52749 // if the reference exists, make the link 52750 if ( ref ) { 52751 delete attrs.ref; 52752 52753 // add in the href and title, if present 52754 attrs.src = ref.href; 52755 if ( ref.title ) { 52756 attrs.title = ref.title; 52757 } 52758 52759 // get rid of the unneeded original text 52760 delete attrs.original; 52761 } 52762 // the reference doesn't exist, so revert to plain text 52763 else { 52764 return attrs.original; 52765 } 52766 break; 52767 } 52768 52769 // convert all the children 52770 i = 1; 52771 52772 // deal with the attribute node, if it exists 52773 if ( attrs ) { 52774 // if there are keys, skip over it 52775 for ( var key in jsonml[ 1 ] ) { 52776 i = 2; 52777 break; 52778 } 52779 // if there aren't, remove it 52780 if ( i === 1 ) { 52781 jsonml.splice( i, 1 ); 52782 } 52783 } 52784 52785 for ( ; i < jsonml.length; ++i ) { 52786 jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options ); 52787 } 52788 52789 return jsonml; 52790} 52791 52792 52793// merges adjacent text nodes into a single node 52794function merge_text_nodes( jsonml ) {
52795 // skip the tag name and attribute hash 52796 var i = extract_attr( jsonml ) ? 2 : 1; 52797 52798 while ( i < jsonml.length ) { 52799 // if it's a string check the next item too 52800 if ( typeof jsonml[ i ] === "string" ) { 52801 if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) { 52802 // merge the second string into the first and remove it 52803 jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ]; 52804 } 52805 else { 52806 ++i; 52807 } 52808 } 52809 // if it's not a string recurse 52810 else { 52811 merge_text_nodes( jsonml[ i ] ); 52812 ++i; 52813 } 52814 } 52815} 52816 52817} )( (function() { 52818 if ( typeof exports === "undefined" ) { 52819 window.markdown = {}; 52820 return window.markdown; 52821 } 52822 else { 52823 return exports; 52824 } 52825} )() ); 52826 52827/* =================================================== 52828 * bootstrap-markdown.js v2.10.0 52829 * http://github.com/toopay/bootstrap-markdown 52830 * =================================================== 52831 * Copyright 2013-2016 Taufan Aditya 52832 * 52833 * Licensed under the Apache License, Version 2.0 (the "License"); 52834 * you may not use this file except in compliance with the License. 52835 * You may obtain a copy of the License at 52836 * 52837 * http://www.apache.org/licenses/LICENSE-2.0 52838 * 52839 * Unless required by applicable law or agreed to in writing, software 52840 * distributed under the License is distributed on an "AS IS" BASIS, 52841 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 52842 * See the License for the specific language governing permissions and 52843 * limitations under the License. 52844 * ========================================================== */ 52845 52846(function(factory){ 52847 if (typeof define === "function" && define.amd) { 52848 //RequireJS 52849 define(["jquery"], factory); 52850 } else if (typeof exports === 'object') { 52851 //Backbone.js 52852 factory(require('jquery')); 52853 } else { 52854 //Jquery plugin 52855 factory(jQuery); 52856 } 52857}(function($){ 52858 "use strict"; // jshint ;_; 52859 52860 /* MARKDOWN CLASS DEFINITION 52861 * ========================== */ 52862 52863 var Markdown = function (element, options) { 52864 // @TODO : remove this BC on next major release 52865 // @see : https://github.com/toopay/bootstrap-markdown/issues/109 52866 var opts = ['autofocus', 'savable', 'hideable', 'width', 52867 'height', 'resize', 'iconlibrary', 'language', 52868 'footer', 'fullscreen', 'hiddenButtons', 'disabledButtons']; 52869 $.each(opts,function(_, opt){ 52870 if (typeof $(element).data(opt) !== 'undefined') { 52871 options = typeof options == 'object' ? options : {} 52872 options[opt] = $(element).data(opt) 52873 } 52874 }); 52875 // End BC 52876 52877 // Class Properties 52878 this.$ns = 'bootstrap-markdown'; 52879 this.$element = $(element); 52880 this.$editable = {el:null, type:null,attrKeys:[], attrValues:[], content:null}; 52881 this.$options = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options')); 52882 this.$oldContent = null; 52883 this.$isPreview = false; 52884 this.$isFullscreen = false; 52885 this.$editor = null; 52886 this.$textarea = null; 52887 this.$handler = []; 52888 this.$callback = []; 52889 this.$nextTab = []; 52890 52891 this.showEditor(); 52892 }; 52893 52894 Markdown.prototype = { 52895 52896 constructor: Markdown 52897 52898 , __alterButtons: function(name,alter) { 52899 var handler = this.$handler, isAll = (name == 'all'),that = this; 52900 52901 $.each(handler,function(k,v) { 52902 var halt = true; 52903 if (isAll) { 52904 halt = false; 52905 } else { 52906 halt = v.indexOf(name) < 0; 52907 } 52908 52909 if (halt === false) { 52910 alter(that.$editor.find('button[data-handler="'+v+'"]')); 52911 } 52912 }); 52913 } 52914 52915 , __buildButtons: function(buttonsArray, container) { 52916 var i, 52917 ns = this.$ns, 52918 handler = this.$handler, 52919 callback = this.$callback; 52920 52921 for (i=0;i<buttonsArray.length;i++) { 52922 // Build each group container 52923 var y, btnGroups = buttonsArray[i]; 52924 for (y=0;y<btnGroups.length;y++) { 52925 // Build each button group 52926 var z, 52927 buttons = btnGroups[y].data,
52928 btnGroupContainer = $('<div/>', { 52929 'class': 'btn-group' 52930 }); 52931 52932 for (z=0;z<buttons.length;z++) { 52933 var button = buttons[z], 52934 buttonContainer, buttonIconContainer, 52935 buttonHandler = ns+'-'+button.name, 52936 buttonIcon = this.__getIcon(button.icon), 52937 btnText = button.btnText ? button.btnText : '', 52938 btnClass = button.btnClass ? button.btnClass : 'btn', 52939 tabIndex = button.tabIndex ? button.tabIndex : '-1', 52940 hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '', 52941 hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' ('+hotkey+')' : ''; 52942 52943 // Construct the button object 52944 buttonContainer = $('<button></button>'); 52945 buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass); 52946 if(btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)){ 52947 buttonContainer.removeClass('btn-default'); 52948 } 52949 buttonContainer.attr({ 52950 'type': 'button', 52951 'title': this.__localize(button.title) + hotkeyCaption, 52952 'tabindex': tabIndex, 52953 'data-provider': ns, 52954 'data-handler': buttonHandler, 52955 'data-hotkey': hotkey 52956 }); 52957 if (button.toggle === true){ 52958 buttonContainer.attr('data-toggle', 'button'); 52959 } 52960 buttonIconContainer = $('<span/>'); 52961 buttonIconContainer.addClass(buttonIcon); 52962 buttonIconContainer.prependTo(buttonContainer); 52963 52964 // Attach the button object 52965 btnGroupContainer.append(buttonContainer); 52966 52967 // Register handler and callback 52968 handler.push(buttonHandler); 52969 callback.push(button.callback); 52970 } 52971 52972 // Attach the button group into container dom 52973 container.append(btnGroupContainer); 52974 } 52975 } 52976 52977 return container; 52978 } 52979 , __setListener: function() { 52980 // Set size and resizable Properties 52981 var hasRows = typeof this.$textarea.attr('rows') !== 'undefined', 52982 maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5', 52983 rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows; 52984 52985 this.$textarea.attr('rows',rowsVal); 52986 if (this.$options.resize) { 52987 this.$textarea.css('resize',this.$options.resize); 52988 } 52989 52990 this.$textarea.on({ 52991 'focus' : $.proxy(this.focus, this), 52992 'keyup' : $.proxy(this.keyup, this), 52993 'change' : $.proxy(this.change, this), 52994 'select' : $.proxy(this.select, this) 52995 }); 52996 52997 if (this.eventSupported('keydown')) { 52998 this.$textarea.on('keydown', $.proxy(this.keydown, this)); 52999 } 53000 53001 if (this.eventSupported('keypress')) { 53002 this.$textarea.on('keypress', $.proxy(this.keypress, this)) 53003 } 53004 53005 // Re-attach markdown data 53006 this.$textarea.data('markdown',this); 53007 } 53008 53009 , __handle: function(e) { 53010 var target = $(e.currentTarget), 53011 handler = this.$handler, 53012 callback = this.$callback, 53013 handlerName = target.attr('data-handler'), 53014 callbackIndex = handler.indexOf(handlerName), 53015 callbackHandler = callback[callbackIndex]; 53016 53017 // Trigger the focusin 53018 $(e.currentTarget).focus(); 53019 53020 callbackHandler(this); 53021 53022 // Trigger onChange for each button handle 53023 this.change(this); 53024 53025 // Unless it was the save handler, 53026 // focusin the textarea 53027 if (handlerName.indexOf('cmdSave') < 0) { 53028 this.$textarea.focus(); 53029 } 53030 53031 e.preventDefault(); 53032 } 53033 53034 , __localize: function(string) { 53035 var messages = $.fn.markdown.messages, 53036 language = this.$options.language; 53037 if ( 53038 typeof messages !== 'undefined' && 53039 typeof messages[language] !== 'undefined' && 53040 typeof messages[language][string] !== 'undefined' 53041 ) { 53042 return messages[language][string]; 53043 } 53044 return string; 53045 } 53046 53047 , __getIcon: function(src) { 53048 return typeof src == 'object' ? src[this.$options.iconlibrary] : src; 53049 } 53050 53051 , setFullscreen: function(mode) { 53052 var $editor = this.$editor, 53053 $textarea = this.$textarea; 53054 53055 if (mode === true) { 53056 $editor.addClass('md-fullscreen-mode'); 53057 $('body').addClass('md-nooverflow'); 53058 this.$options.onFullscreen(this); 53059 } else { 53060 $editor.removeClass('md-fullscreen-mode'); 53061 $('body').removeClass('md-nooverflow'); 53062 53063 if (this.$isPreview == true) this.hidePreview().showPreview() 53064 } 53065 53066 this.$isFullscreen = mode; 53067 $textarea.focus(); 53068 } 53069 53070 , showEditor: function() { 53071 var instance = this, 53072 textarea,
53073 ns = this.$ns, 53074 container = this.$element, 53075 originalHeigth = container.css('height'), 53076 originalWidth = container.css('width'), 53077 editable = this.$editable, 53078 handler = this.$handler, 53079 callback = this.$callback, 53080 options = this.$options, 53081 editor = $( '<div/>', { 53082 'class': 'md-editor', 53083 click: function() { 53084 instance.focus(); 53085 } 53086 }); 53087 53088 // Prepare the editor 53089 if (this.$editor === null) { 53090 // Create the panel 53091 var editorHeader = $('<div/>', { 53092 'class': 'md-header btn-toolbar' 53093 }); 53094 53095 // Merge the main & additional button groups together 53096 var allBtnGroups = []; 53097 if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]); 53098 if (options.additionalButtons.length > 0) { 53099 // iterate the additional button groups 53100 $.each(options.additionalButtons[0], function(idx, buttonGroup){ 53101 53102 // see if the group name of the addional group matches an existing group 53103 var matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx){ 53104 return allButtonGroup.name === buttonGroup.name; 53105 }); 53106 53107 // if it matches add the addional buttons to that group, if not just add it to the all buttons group 53108 if(matchingGroups.length > 0) { 53109 matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data); 53110 } else { 53111 allBtnGroups.push(options.additionalButtons[0][idx]); 53112 } 53113 53114 }); 53115 } 53116 53117 // Reduce and/or reorder the button groups 53118 if (options.reorderButtonGroups.length > 0) { 53119 allBtnGroups = allBtnGroups 53120 .filter(function(btnGroup) { 53121 return options.reorderButtonGroups.indexOf(btnGroup.name) > -1; 53122 }) 53123 .sort(function(a, b) { 53124 if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1; 53125 if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1; 53126 return 0; 53127 }); 53128 } 53129 53130 // Build the buttons 53131 if (allBtnGroups.length > 0) { 53132 editorHeader = this.__buildButtons([allBtnGroups], editorHeader); 53133 } 53134 53135 if (options.fullscreen.enable) { 53136 editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(options.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on('click', '.md-control-fullscreen', function(e) { 53137 e.preventDefault(); 53138 instance.setFullscreen(true); 53139 }); 53140 } 53141 53142 editor.append(editorHeader); 53143 53144 // Wrap the textarea 53145 if (container.is('textarea')) { 53146 container.before(editor); 53147 textarea = container; 53148 textarea.addClass('md-input'); 53149 editor.append(textarea); 53150 } else { 53151 var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(), 53152 currentContent = $.trim(rawContent); 53153 53154 // This is some arbitrary content that could be edited 53155 textarea = $('<textarea/>', { 53156 'class': 'md-input', 53157 'val' : currentContent 53158 }); 53159 53160 editor.append(textarea); 53161 53162 // Save the editable 53163 editable.el = container; 53164 editable.type = container.prop('tagName').toLowerCase(); 53165 editable.content = container.html(); 53166 53167 $(container[0].attributes).each(function(){ 53168 editable.attrKeys.push(this.nodeName); 53169 editable.attrValues.push(this.nodeValue); 53170 }); 53171 53172 // Set editor to blocked the original container 53173 container.replaceWith(editor); 53174 } 53175
53176 var editorFooter = $('<div/>', { 53177 'class': 'md-footer' 53178 }), 53179 createFooter = false, 53180 footer = ''; 53181 // Create the footer if savable 53182 if (options.savable) { 53183 createFooter = true; 53184 var saveHandler = 'cmdSave'; 53185 53186 // Register handler and callback 53187 handler.push(saveHandler); 53188 callback.push(options.onSave); 53189 53190 editorFooter.append('<button class="btn btn-success" data-provider="' 53191 + ns 53192 + '" data-handler="' 53193 + saveHandler 53194 + '"><i class="icon icon-white icon-ok"></i> ' 53195 + this.__localize('Save') 53196 + '</button>'); 53197 53198 53199 } 53200 53201 footer = typeof options.footer === 'function' ? options.footer(this) : options.footer; 53202 53203 if ($.trim(footer) !== '') { 53204 createFooter = true; 53205 editorFooter.append(footer); 53206 } 53207 53208 if (createFooter) editor.append(editorFooter); 53209 53210 // Set width 53211 if (options.width && options.width !== 'inherit') { 53212 if (jQuery.isNumeric(options.width)) { 53213 editor.css('display', 'table'); 53214 textarea.css('width', options.width + 'px'); 53215 } else { 53216 editor.addClass(options.width); 53217 } 53218 } 53219 53220 // Set height 53221 if (options.height && options.height !== 'inherit') { 53222 if (jQuery.isNumeric(options.height)) { 53223 var height = options.height; 53224 if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight()); 53225 if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight()); 53226 textarea.css('height', height + 'px'); 53227 } else { 53228 editor.addClass(options.height); 53229 } 53230 } 53231 53232 // Reference 53233 this.$editor = editor; 53234 this.$textarea = textarea; 53235 this.$editable = editable; 53236 this.$oldContent = this.getContent(); 53237 53238 this.__setListener(); 53239 53240 // Set editor attributes, data short-hand API and listener 53241 this.$editor.attr('id',(new Date()).getTime()); 53242 this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this)); 53243 53244 if (this.$element.is(':disabled') || this.$element.is('[readonly]')) { 53245 this.$editor.addClass('md-editor-disabled'); 53246 this.disableButtons('all'); 53247 } 53248 53249 if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') { 53250 editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() { 53251 var $button = $(this), 53252 hotkey = $button.attr('data-hotkey'); 53253 if (hotkey.toLowerCase() !== '') { 53254 textarea.bind('keydown', hotkey, function() { 53255 $button.trigger('click'); 53256 return false; 53257 }); 53258 } 53259 }); 53260 } 53261 53262 if (options.initialstate === 'preview') { 53263 this.showPreview(); 53264 } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) { 53265 this.setFullscreen(true); 53266 } 53267 53268 } else { 53269 this.$editor.show(); 53270 } 53271 53272 if (options.autofocus) { 53273 this.$textarea.focus(); 53274 this.$editor.addClass('active'); 53275 } 53276 53277 if (options.fullscreen.enable && options.fullscreen !== false) { 53278 this.$editor.append('<div class="md-fullscreen-controls">' 53279 + '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">' 53280 + '</span></a>' 53281 + '</div>'); 53282 this.$editor.on('click', '.exit-fullscreen', function(e) { 53283 e.preventDefault(); 53284 instance.setFullscreen(false); 53285 }); 53286 } 53287 53288 // hide hidden buttons from options 53289 this.hideButtons(options.hiddenButtons); 53290 53291 // disable disabled buttons from options 53292 this.disableButtons(options.disabledButtons); 53293 53294 // Trigger the onShow hook 53295 options.onShow(this); 53296 53297 return this; 53298 } 53299 53300 , parseContent: function(val) { 53301 var content; 53302 53303 // parse with supported markdown parser 53304 var val = val || this.$textarea.val(); 53305 53306 if (this.$options.parser) { 53307 content = this.$options.parser(val); 53308 } else if (typeof markdown == 'object') { 53309 content = markdown.toHTML(val); 53310 } else if (typeof marked == 'function') { 53311 content = marked(val); 53312 } else { 53313 content = val; 53314 } 53315 53316 return content; 53317 } 53318 53319 , showPreview: function() { 53320 var options = this.$options, 53321 container = this.$textarea,
53322 afterContainer = container.next(), 53323 replacementContainer = $('<div/>',{'class':'md-preview','data-provider':'markdown-preview'}), 53324 content, 53325 callbackContent; 53326 53327 if (this.$isPreview == true) { 53328 // Avoid sequenced element creation on missused scenario 53329 // @see https://github.com/toopay/bootstrap-markdown/issues/170 53330 return this; 53331 } 53332 53333 // Give flag that tell the editor enter preview mode 53334 this.$isPreview = true; 53335 // Disable all buttons 53336 this.disableButtons('all').enableButtons('cmdPreview'); 53337 53338 // Try to get the content from callback 53339 callbackContent = options.onPreview(this); 53340 // Set the content based from the callback content if string otherwise parse value from textarea 53341 content = typeof callbackContent == 'string' ? callbackContent : this.parseContent(); 53342 53343 // Build preview element 53344 replacementContainer.html(content); 53345 53346 if (afterContainer && afterContainer.attr('class') == 'md-footer') { 53347 // If there is footer element, insert the preview container before it 53348 replacementContainer.insertBefore(afterContainer); 53349 } else { 53350 // Otherwise, just append it after textarea 53351 container.parent().append(replacementContainer); 53352 } 53353 53354 // Set the preview element dimensions 53355 replacementContainer.css({ 53356 width: container.outerWidth() + 'px', 53357 height: container.outerHeight() + 'px' 53358 }); 53359 53360 if (this.$options.resize) { 53361 replacementContainer.css('resize',this.$options.resize); 53362 } 53363 53364 // Hide the last-active textarea 53365 container.hide(); 53366 53367 // Attach the editor instances 53368 replacementContainer.data('markdown',this); 53369 53370 if (this.$element.is(':disabled') || this.$element.is('[readonly]')) { 53371 this.$editor.addClass('md-editor-disabled'); 53372 this.disableButtons('all'); 53373 } 53374 53375 return this; 53376 } 53377 53378 , hidePreview: function() { 53379 // Give flag that tell the editor quit preview mode 53380 this.$isPreview = false; 53381 53382 // Obtain the preview container 53383 var container = this.$editor.find('div[data-provider="markdown-preview"]'); 53384 53385 // Remove the preview container 53386 container.remove(); 53387 53388 // Enable all buttons 53389 this.enableButtons('all'); 53390 // Disable configured disabled buttons 53391 this.disableButtons(this.$options.disabledButtons); 53392 53393 // Back to the editor 53394 this.$textarea.show(); 53395 this.__setListener(); 53396 53397 return this; 53398 } 53399 53400 , isDirty: function() { 53401 return this.$oldContent != this.getContent(); 53402 } 53403 53404 , getContent: function() { 53405 return this.$textarea.val(); 53406 } 53407 53408 , setContent: function(content) { 53409 this.$textarea.val(content); 53410 53411 return this; 53412 } 53413 53414 , findSelection: function(chunk) { 53415 var content = this.getContent(), startChunkPosition; 53416 53417 if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) { 53418 var oldSelection = this.getSelection(), selection; 53419 53420 this.setSelection(startChunkPosition,startChunkPosition+chunk.length); 53421 selection = this.getSelection(); 53422 53423 this.setSelection(oldSelection.start,oldSelection.end); 53424 53425 return selection; 53426 } else { 53427 return null; 53428 } 53429 } 53430 53431 , getSelection: function() { 53432 53433 var e = this.$textarea[0]; 53434 53435 return ( 53436 53437 ('selectionStart' in e && function() { 53438 var l = e.selectionEnd - e.selectionStart; 53439 return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }; 53440 }) || 53441 53442 /* browser not supported */ 53443 function() { 53444 return null; 53445 } 53446 53447 )(); 53448 53449 } 53450 53451 , setSelection: function(start,end) { 53452 53453 var e = this.$textarea[0]; 53454 53455 return ( 53456 53457 ('selectionStart' in e && function() { 53458 e.selectionStart = start; 53459 e.selectionEnd = end; 53460 return; 53461 }) || 53462 53463 /* browser not supported */ 53464 function() { 53465 return null; 53466 } 53467 53468 )(); 53469 53470 } 53471 53472 , replaceSelection: function(text) { 53473 53474 var e = this.$textarea[0]; 53475 53476 return ( 53477 53478 ('selectionStart' in e && function() { 53479 e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length); 53480 // Set cursor to the last replacement end 53481 e.selectionStart = e.value.length; 53482 return this; 53483 }) || 53484 53485 /* browser not supported */ 53486 function() { 53487 e.value += text; 53488 return jQuery(e); 53489 } 53490 53491 )(); 53492 } 53493 53494 , getNextTab: function() { 53495 // Shift the nextTab 53496 if (this.$nextTab.length === 0) { 53497 return null; 53498 } else { 53499 var nextTab, tab = this.$nextTab.shift(); 53500 53501 if (typeof tab == 'function') { 53502 nextTab = tab(); 53503 } else if (typeof tab == 'object' && tab.length > 0) { 53504 nextTab = tab; 53505 } 53506 53507 return nextTab; 53508 } 53509 } 53510 53511 , setNextTab: function(start,end) { 53512 // Push new selection into nextTab collections 53513 if (typeof start == 'string') { 53514 var that = this; 53515 this.$nextTab.push(function(){ 53516 return that.findSelection(start); 53517 }); 53518 } else if (typeof start == 'number' && typeof end == 'number') {
53519 var oldSelection = this.getSelection(); 53520 53521 this.setSelection(start,end); 53522 this.$nextTab.push(this.getSelection()); 53523 53524 this.setSelection(oldSelection.start,oldSelection.end); 53525 } 53526 53527 return; 53528 } 53529 53530 , __parseButtonNameParam: function (names) { 53531 return typeof names == 'string' ? 53532 names.split(' ') : 53533 names; 53534 53535 } 53536 53537 , enableButtons: function(name) { 53538 var buttons = this.__parseButtonNameParam(name), 53539 that = this; 53540 53541 $.each(buttons, function(i, v) { 53542 that.__alterButtons(buttons[i], function (el) { 53543 el.removeAttr('disabled'); 53544 }); 53545 }); 53546 53547 return this; 53548 } 53549 53550 , disableButtons: function(name) { 53551 var buttons = this.__parseButtonNameParam(name), 53552 that = this; 53553 53554 $.each(buttons, function(i, v) { 53555 that.__alterButtons(buttons[i], function (el) { 53556 el.attr('disabled','disabled'); 53557 }); 53558 }); 53559 53560 return this; 53561 } 53562 53563 , hideButtons: function(name) { 53564 var buttons = this.__parseButtonNameParam(name), 53565 that = this; 53566 53567 $.each(buttons, function(i, v) { 53568 that.__alterButtons(buttons[i], function (el) { 53569 el.addClass('hidden'); 53570 }); 53571 }); 53572 53573 return this; 53574 } 53575 53576 , showButtons: function(name) { 53577 var buttons = this.__parseButtonNameParam(name), 53578 that = this; 53579 53580 $.each(buttons, function(i, v) { 53581 that.__alterButtons(buttons[i], function (el) { 53582 el.removeClass('hidden'); 53583 }); 53584 }); 53585 53586 return this; 53587 } 53588 53589 , eventSupported: function(eventName) { 53590 var isSupported = eventName in this.$element; 53591 if (!isSupported) { 53592 this.$element.setAttribute(eventName, 'return;'); 53593 isSupported = typeof this.$element[eventName] === 'function'; 53594 } 53595 return isSupported; 53596 } 53597 53598 , keyup: function (e) { 53599 var blocked = false; 53600 switch(e.keyCode) { 53601 case 40: // down arrow 53602 case 38: // up arrow 53603 case 16: // shift 53604 case 17: // ctrl 53605 case 18: // alt 53606 break; 53607 53608 case 9: // tab 53609 var nextTab; 53610 if (nextTab = this.getNextTab(),nextTab !== null) { 53611 // Get the nextTab if exists 53612 var that = this; 53613 setTimeout(function(){ 53614 that.setSelection(nextTab.start,nextTab.end); 53615 },500); 53616 53617 blocked = true; 53618 } else { 53619 // The next tab memory contains nothing... 53620 // check the cursor position to determine tab action 53621 var cursor = this.getSelection(); 53622 53623 if (cursor.start == cursor.end && cursor.end == this.getContent().length) { 53624 // The cursor already reach the end of the content 53625 blocked = false; 53626 } else { 53627 // Put the cursor to the end 53628 this.setSelection(this.getContent().length,this.getContent().length); 53629 53630 blocked = true; 53631 } 53632 } 53633 53634 break; 53635 53636 case 13: // enter 53637 blocked = false; 53638 break; 53639 case 27: // escape 53640 if (this.$isFullscreen) this.setFullscreen(false); 53641 blocked = false; 53642 break; 53643 53644 default: 53645 blocked = false; 53646 } 53647 53648 if (blocked) { 53649 e.stopPropagation(); 53650 e.preventDefault(); 53651 } 53652 53653 this.$options.onChange(this); 53654 } 53655 53656 , change: function(e) { 53657 this.$options.onChange(this); 53658 return this; 53659 } 53660 , select: function (e) { 53661 this.$options.onSelect(this); 53662 return this; 53663 } 53664 , focus: function (e) { 53665 var options = this.$options, 53666 isHideable = options.hideable, 53667 editor = this.$editor; 53668 53669 editor.addClass('active'); 53670 53671 // Blur other markdown(s) 53672 $(document).find('.md-editor').each(function(){ 53673 if ($(this).attr('id') !== editor.attr('id')) { 53674 var attachedMarkdown; 53675 53676 if (attachedMarkdown = $(this).find('textarea').data('markdown'), 53677 attachedMarkdown === null) { 53678 attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown'); 53679 } 53680 53681 if (attachedMarkdown) { 53682 attachedMarkdown.blur(); 53683 } 53684 } 53685 }); 53686 53687 // Trigger the onFocus hook 53688 options.onFocus(this); 53689 53690 return this; 53691 } 53692 53693 , blur: function (e) { 53694 var options = this.$options, 53695 isHideable = options.hideable, 53696 editor = this.$editor, 53697 editable = this.$editable; 53698 53699 if (editor.hasClass('active') || this.$element.parent().length === 0) { 53700 editor.removeClass('active'); 53701 53702 if (isHideable) { 53703 // Check for editable elements 53704 if (editable.el !== null) { 53705 // Build the original element 53706 var oldElement = $('<'+editable.type+'/>'), 53707 content = this.getContent(), 53708 currentContent = this.parseContent(content); 53709 53710 $(editable.attrKeys).each(function(k,v) { 53711 oldElement.attr(editable.attrKeys[k],editable.attrValues[k]); 53712 }); 53713 53714 // Get the editor content 53715 oldElement.html(currentContent); 53716 53717 editor.replaceWith(oldElement); 53718 } else { 53719 editor.hide(); 53720 } 53721 } 53722 53723 // Trigger the onBlur hook 53724 options.onBlur(this); 53725 } 53726 53727 return this; 53728 } 53729 53730 }; 53731 53732 /* MARKDOWN PLUGIN DEFINITION 53733 * ========================== */ 53734 53735 var old = $.fn.markdown; 53736 53737 $.fn.markdown = function (option) { 53738 return this.each(function () { 53739 var $this = $(this) 53740 , data = $this.data('markdown') 53741 , options = typeof option == 'object' && option; 53742 if (!data) $this.data('markdown', (data = new Markdown(this, options))) 53743 }) 53744 }; 53745 53746 $.fn.markdown.messages = {}; 53747 53748 $.fn.markdown.defaults = { 53749 /* Editor Properties */ 53750 autofocus: false, 53751 hideable: false, 53752 savable: false, 53753 width: 'inherit', 53754 height: 'inherit', 53755 resize: 'none', 53756 iconlibrary: 'glyph', 53757 language: 'en', 53758 initialstate: 'editor', 53759 parser: null, 53760 53761 /* Buttons Properties */ 53762 buttons: [ 53763 [{ 53764 name: 'groupFont', 53765 data: [{ 53766 name: 'cmdBold', 53767 hotkey: 'Ctrl+B', 53768 title: 'Bold', 53769 icon: { glyph: 'glyphicon glyphicon-bold', fa: 'fa fa-bold', 'fa-3': 'icon-bold' }, 53770 callback: function(e){ 53771 // Give/remove ** surround the selection 53772 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 53773 53774 if (selected.length === 0) { 53775 // Give extra word 53776 chunk = e.__localize('strong text'); 53777 } else { 53778 chunk = selected.text; 53779 } 53780 53781 // transform selection and set the cursor into chunked text 53782 if (content.substr(selected.start-2,2) === '**' 53783 && content.substr(selected.end,2) === '**' ) { 53784 e.setSelection(selected.start-2,selected.end+2); 53785 e.replaceSelection(chunk); 53786 cursor = selected.start-2; 53787 } else { 53788 e.replaceSelection('**'+chunk+'**'); 53789 cursor = selected.start+2; 53790 } 53791 53792 // Set the cursor 53793 e.setSelection(cursor,cursor+chunk.length); 53794 } 53795 },{ 53796 name: 'cmdItalic', 53797 title: 'Italic', 53798 hotkey: 'Ctrl+I', 53799 icon: { glyph: 'glyphicon glyphicon-italic', fa: 'fa fa-italic', 'fa-3': 'icon-italic' }, 53800 callback: function(e){ 53801 // Give/remove * surround the selection 53802 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 53803 53804 if (selected.length === 0) { 53805 // Give extra word 53806 chunk = e.__localize('emphasized text'); 53807 } else { 53808 chunk = selected.text; 53809 } 53810 53811 // transform selection and set the cursor into chunked text 53812 if (content.substr(selected.start-1,1) === '_' 53813 && content.substr(selected.end,1) === '_' ) { 53814 e.setSelection(selected.start-1,selected.end+1); 53815 e.replaceSelection(chunk); 53816 cursor = selected.start-1; 53817 } else { 53818 e.replaceSelection('_'+chunk+'_'); 53819 cursor = selected.start+1; 53820 } 53821 53822 // Set the cursor 53823 e.setSelection(cursor,cursor+chunk.length); 53824 } 53825 },{ 53826 name: 'cmdHeading', 53827 title: 'Heading', 53828 hotkey: 'Ctrl+H', 53829 icon: { glyph: 'glyphicon glyphicon-header', fa: 'fa fa-header', 'fa-3': 'icon-font' }, 53830 callback: function(e){ 53831 // Append/remove ### surround the selection 53832 var chunk, cursor, selected = e.getSelection(), content = e.getContent(), pointer, prevChar; 53833 53834 if (selected.length === 0) { 53835 // Give extra word 53836 chunk = e.__localize('heading text'); 53837 } else { 53838 chunk = selected.text + '\n'; 53839 } 53840 53841 // transform selection and set the cursor into chunked text 53842 if ((pointer = 4, content.substr(selected.start-pointer,pointer) === '### ') 53843 || (pointer = 3, content.substr(selected.start-pointer,pointer) === '###')) { 53844 e.setSelection(selected.start-pointer,selected.end); 53845 e.replaceSelection(chunk); 53846 cursor = selected.start-pointer; 53847 } else if (selected.start > 0 && (prevChar = content.substr(selected.start-1,1), !!prevChar && prevChar != '\n')) { 53848 e.replaceSelection('\n\n### '+chunk); 53849 cursor = selected.start+6; 53850 } else { 53851 // Empty string before element 53852 e.replaceSelection('### '+chunk); 53853 cursor = selected.start+4; 53854 } 53855 53856 // Set the cursor 53857 e.setSelection(cursor,cursor+chunk.length); 53858 } 53859 }] 53860 },{ 53861 name: 'groupLink', 53862 data: [{ 53863 name: 'cmdUrl', 53864 title: 'URL/Link', 53865 hotkey: 'Ctrl+L', 53866 icon: { glyph: 'glyphicon glyphicon-link', fa: 'fa fa-link', 'fa-3': 'icon-link' }, 53867 callback: function(e){ 53868 // Give [] surround the selection and prepend the link 53869 var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link; 53870 53871 if (selected.length === 0) { 53872 // Give extra word 53873 chunk = e.__localize('enter link description here'); 53874 } else { 53875 chunk = selected.text; 53876 } 53877 53878 link = prompt(e.__localize('Insert Hyperlink'),'http://'); 53879 53880 var urlRegex = new RegExp('^((http|https)://|(mailto:)|(//))[a-z0-9]', 'i'); 53881 if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) { 53882 var sanitizedLink = $('<div>'+link+'</div>').text(); 53883 53884 // transform selection and set the cursor into chunked text 53885 e.replaceSelection('['+chunk+']('+sanitizedLink+')'); 53886 cursor = selected.start+1; 53887 53888 // Set the cursor 53889 e.setSelection(cursor,cursor+chunk.length); 53890 } 53891 } 53892 },{ 53893 name: 'cmdImage', 53894 title: 'Image', 53895 hotkey: 'Ctrl+G', 53896 icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' }, 53897 callback: function(e){ 53898 // Give ![] surround the selection and prepend the image link 53899 var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link; 53900 53901 if (selected.length === 0) { 53902 // Give extra word 53903 chunk = e.__localize('enter image description here'); 53904 } else { 53905 chunk = selected.text; 53906 } 53907 53908 link = prompt(e.__localize('Insert Image Hyperlink'),'http://'); 53909 53910 var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i'); 53911 if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) { 53912 var sanitizedLink = $('<div>'+link+'</div>').text(); 53913 53914 // transform selection and set the cursor into chunked text 53915 e.replaceSelection('+'")'); 53916 cursor = selected.start+2; 53917 53918 // Set the next tab 53919 e.setNextTab(e.__localize('enter image title here')); 53920 53921 // Set the cursor 53922 e.setSelection(cursor,cursor+chunk.length); 53923 } 53924 } 53925 }] 53926 },{ 53927 name: 'groupMisc', 53928 data: [{ 53929 name: 'cmdList', 53930 hotkey: 'Ctrl+U', 53931 title: 'Unordered List', 53932 icon: { glyph: 'glyphicon glyphicon-list', fa: 'fa fa-list', 'fa-3': 'icon-list-ul' }, 53933 callback: function(e){ 53934 // Prepend/Give - surround the selection 53935 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 53936 53937 // transform selection and set the cursor into chunked text 53938 if (selected.length === 0) { 53939 // Give extra word 53940 chunk = e.__localize('list text here'); 53941 53942 e.replaceSelection('- '+chunk); 53943 // Set the cursor 53944 cursor = selected.start+2; 53945 } else { 53946 if (selected.text.indexOf('\n') < 0) { 53947 chunk = selected.text; 53948 53949 e.replaceSelection('- '+chunk); 53950 53951 // Set the cursor 53952 cursor = selected.start+2; 53953 } else { 53954 var list = []; 53955 53956 list = selected.text.split('\n'); 53957 chunk = list[0]; 53958 53959 $.each(list,function(k,v) { 53960 list[k] = '- '+v; 53961 }); 53962 53963 e.replaceSelection('\n\n'+list.join('\n')); 53964 53965 // Set the cursor 53966 cursor = selected.start+4; 53967 } 53968 } 53969 53970 // Set the cursor 53971 e.setSelection(cursor,cursor+chunk.length); 53972 } 53973 }, 53974 { 53975 name: 'cmdListO', 53976 hotkey: 'Ctrl+O', 53977 title: 'Ordered List', 53978 icon: { glyph: 'glyphicon glyphicon-th-list', fa: 'fa fa-list-ol', 'fa-3': 'icon-list-ol' }, 53979 callback: function(e) { 53980 53981 // Prepend/Give - surround the selection 53982 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 53983 53984 // transform selection and set the cursor into chunked text 53985 if (selected.length === 0) { 53986 // Give extra word 53987 chunk = e.__localize('list text here'); 53988 e.replaceSelection('1. '+chunk); 53989 // Set the cursor 53990 cursor = selected.start+3; 53991 } else { 53992 if (selected.text.indexOf('\n') < 0) { 53993 chunk = selected.text; 53994 53995 e.replaceSelection('1. '+chunk); 53996 53997 // Set the cursor 53998 cursor = selected.start+3; 53999 } else { 54000 var list = []; 54001 54002 list = selected.text.split('\n'); 54003 chunk = list[0]; 54004 54005 $.each(list,function(k,v) { 54006 list[k] = '1. '+v; 54007 }); 54008 54009 e.replaceSelection('\n\n'+list.join('\n')); 54010 54011 // Set the cursor 54012 cursor = selected.start+5; 54013 } 54014 } 54015 54016 // Set the cursor 54017 e.setSelection(cursor,cursor+chunk.length); 54018 } 54019 }, 54020 { 54021 name: 'cmdCode', 54022 hotkey: 'Ctrl+K', 54023 title: 'Code', 54024 icon: { glyph: 'glyphicon glyphicon-asterisk', fa: 'fa fa-code', 'fa-3': 'icon-code' }, 54025 callback: function(e) { 54026 // Give/remove ** surround the selection 54027 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 54028 54029 if (selected.length === 0) { 54030 // Give extra word 54031 chunk = e.__localize('code text here'); 54032 } else { 54033 chunk = selected.text; 54034 } 54035 54036 // transform selection and set the cursor into chunked text 54037 if (content.substr(selected.start-4,4) === '```\n' 54038 && content.substr(selected.end,4) === '\n```') { 54039 e.setSelection(selected.start-4, selected.end+4); 54040 e.replaceSel
54040ection(chunk); 54041 cursor = selected.start-4; 54042 } else if (content.substr(selected.start-1,1) === '`' 54043 && content.substr(selected.end,1) === '`') { 54044 e.setSelection(selected.start-1,selected.end+1); 54045 e.replaceSelection(chunk); 54046 cursor = selected.start-1; 54047 } else if (content.indexOf('\n') > -1) { 54048 e.replaceSelection('```\n'+chunk+'\n```'); 54049 cursor = selected.start+4; 54050 } else { 54051 e.replaceSelection('`'+chunk+'`'); 54052 cursor = selected.start+1; 54053 } 54054 54055 // Set the cursor 54056 e.setSelection(cursor,cursor+chunk.length); 54057 } 54058 }, 54059 { 54060 name: 'cmdQuote', 54061 hotkey: 'Ctrl+Q', 54062 title: 'Quote', 54063 icon: { glyph: 'glyphicon glyphicon-comment', fa: 'fa fa-quote-left', 'fa-3': 'icon-quote-left' }, 54064 callback: function(e) { 54065 // Prepend/Give - surround the selection 54066 var chunk, cursor, selected = e.getSelection(), content = e.getContent(); 54067 54068 // transform selection and set the cursor into chunked text 54069 if (selected.length === 0) { 54070 // Give extra word 54071 chunk = e.__localize('quote here'); 54072 54073 e.replaceSelection('> '+chunk); 54074 54075 // Set the cursor 54076 cursor = selected.start+2; 54077 } else { 54078 if (selected.text.indexOf('\n') < 0) { 54079 chunk = selected.text; 54080 54081 e.replaceSelection('> '+chunk); 54082 54083 // Set the cursor 54084 cursor = selected.start+2; 54085 } else { 54086 var list = []; 54087 54088 list = selected.text.split('\n'); 54089 chunk = list[0]; 54090 54091 $.each(list,function(k,v) { 54092 list[k] = '> '+v; 54093 }); 54094 54095 e.replaceSelection('\n\n'+list.join('\n')); 54096 54097 // Set the cursor 54098 cursor = selected.start+4; 54099 } 54100 } 54101 54102 // Set the cursor 54103 e.setSelection(cursor,cursor+chunk.length); 54104 } 54105 }] 54106 },{ 54107 name: 'groupUtil', 54108 data: [{ 54109 name: 'cmdPreview', 54110 toggle: true, 54111 hotkey: 'Ctrl+P', 54112 title: 'Preview', 54113 btnText: 'Preview', 54114 btnClass: 'btn btn-primary btn-sm', 54115 icon: { glyph: 'glyphicon glyphicon-search', fa: 'fa fa-search', 'fa-3': 'icon-search' }, 54116 callback: function(e){ 54117 // Check the preview mode and toggle based on this flag 54118 var isPreview = e.$isPreview,content; 54119 54120 if (isPreview === false) { 54121 // Give flag that tell the editor enter preview mode 54122 e.showPreview(); 54123 } else { 54124 e.hidePreview(); 54125 } 54126 } 54127 }] 54128 }] 54129 ], 54130 additionalButtons:[], // Place to hook more buttons by code 54131 reorderButtonGroups:[], 54132 hiddenButtons:[], // Default hidden buttons 54133 disabledButtons:[], // Default disabled buttons 54134 footer: '', 54135 fullscreen: { 54136 enable: true, 54137 icons: { 54138 fullscreenOn: { 54139 fa: 'fa fa-expand', 54140 glyph: 'glyphicon glyphicon-fullscreen', 54141 'fa-3': 'icon-resize-full' 54142 }, 54143 fullscreenOff: { 54144 fa: 'fa fa-compress', 54145 glyph: 'glyphicon glyphicon-fullscreen', 54146 'fa-3': 'icon-resize-small' 54147 } 54148 } 54149 }, 54150 54151 /* Events hook */ 54152 onShow: function (e) {}, 54153 onPreview: function (e) {}, 54154 onSave: function (e) {}, 54155 onBlur: function (e) {}, 54156 onFocus: function (e) {}, 54157 onChange: function(e) {}, 54158 onFullscreen: function(e) {}, 54159 onSelect: function (e) {} 54160 }; 54161 54162 $.fn.markdown.Constructor = Markdown; 54163 54164 54165 /* MARKDOWN NO CONFLICT 54166 * ==================== */ 54167 54168 $.fn.markdown.noConflict = function () { 54169 $.fn.markdown = old; 54170 return this; 54171 }; 54172 54173 /* MARKDOWN GLOBAL FUNCTION & DATA-API 54174 * ==================================== */ 54175 var initMarkdown = function(el) { 54176 var $this = el; 54177 54178 if ($this.data('markdown')) { 54179 $this.data('markdown').showEditor(); 54180 return; 54181 } 54182 54183 $this.markdown() 54184 }; 54185 54186 var blurNonFocused = function(e) { 54187 var $activeElement = $(document.activeElement); 54188 54189 // Blur event 54190 $(document).find('.md-editor').each(function(){ 54191 var $this = $(this), 54192 focused = $activeElement.closest('.md-editor')[0] === this, 54193 attachedMarkdown = $this.find('textarea').data('markdown') || 54194 $this.find('div[data-provider="markdown-preview"]').data('markdown'); 54195 54196 if (attachedMarkdown && !focused) { 54197 attachedMarkdown.blur(); 54198 } 54199 }) 54200 }; 54201 54202 $(document)
vendor: 8,498 bytes, lines 54203-54511
54203 .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function (e) { 54204 initMarkdown($(this)); 54205 e.preventDefault(); 54206 }) 54207 .on('click focusin', function (e) { 54208 blurNonFocused(e); 54209 }) 54210 .ready(function(){ 54211 $('textarea[data-provide="markdown"]').each(function(){ 54212 initMarkdown($(this)); 54213 }) 54214 }); 54215 54216})); 54217 54218"use strict"; 54219$.fn.markdown.defaults.iconlibrary = 'fa'; 54220$.fn.markdown.defaults.buttons[0][0]['data'][2]['icon']['fa'] = 'fa fa-heading'; 54221$.fn.markdown.defaults.buttons[0][1]['data'][1]['icon']['fa'] = 'fa fa-image'; 54222$.fn.markdown.defaults.buttons[0][2]['data'][1]['icon']['fa'] = 'fa fa-list-ol'; 54223 54224/*! 54225 * jQuery Validation Plugin v1.19.0 54226 * 54227 * https://jqueryvalidation.org/ 54228 * 54229 * Copyright (c) 2018 Jörn Zaefferer 54230 * Released under the MIT license 54231 */ 54232(function( factory ) { 54233 if ( typeof define === "function" && define.amd ) { 54234 define( ["jquery"], factory ); 54235 } else if (typeof module === "object" && module.exports) { 54236 module.exports = factory( require( "jquery" ) ); 54237 } else { 54238 factory( jQuery ); 54239 } 54240}(function( $ ) { 54241 54242$.extend( $.fn, { 54243 54244 // https://jqueryvalidation.org/validate/ 54245 validate: function( options ) { 54246 54247 // If nothing is selected, return nothing; can't chain anyway 54248 if ( !this.length ) { 54249 if ( options && options.debug && window.console ) { 54250 console.warn( "Nothing selected, can't validate, returning nothing." ); 54251 } 54252 return; 54253 } 54254 54255 // Check if a validator for this form was already created 54256 var validator = $.data( this[ 0 ], "validator" ); 54257 if ( validator ) { 54258 return validator; 54259 } 54260 54261 // Add novalidate tag if HTML5. 54262 this.attr( "novalidate", "novalidate" ); 54263 54264 validator = new $.validator( options, this[ 0 ] ); 54265 $.data( this[ 0 ], "validator", validator ); 54266 54267 if ( validator.settings.onsubmit ) { 54268 54269 this.on( "click.validate", ":submit", function( event ) { 54270 54271 // Track the used submit button to properly handle scripted 54272 // submits later. 54273 validator.submitButton = event.currentTarget; 54274 54275 // Allow suppressing validation by adding a cancel class to the submit button 54276 if ( $( this ).hasClass( "cancel" ) ) { 54277 validator.cancelSubmit = true; 54278 } 54279 54280 // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button 54281 if ( $( this ).attr( "formnovalidate" ) !== undefined ) { 54282 validator.cancelSubmit = true; 54283 } 54284 } ); 54285 54286 // Validate the form on submit 54287 this.on( "submit.validate", function( event ) { 54288 if ( validator.settings.debug ) { 54289 54290 // Prevent form submit to be able to see console output 54291 event.preventDefault(); 54292 } 54293 54294 function handle() { 54295 var hidden, result; 54296 54297 // Insert a hidden input as a replacement for the missing submit button 54298 // The hidden input is inserted in two cases: 54299 // - A user defined a `submitHandler` 54300 // - There was a pending request due to `remote` method and `stopRequest()` 54301 // was called to submit the form in case it's valid 54302 if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) { 54303 hidden = $( "<input type='hidden'/>" ) 54304 .attr( "name", validator.submitButton.name ) 54305 .val( $( validator.submitButton ).val() ) 54306 .appendTo( validator.currentForm ); 54307 } 54308 54309 if ( validator.settings.submitHandler && !validator.settings.debug ) { 54310 result = validator.settings.submitHandler.call( validator, validator.currentForm, event ); 54311 if ( hidden ) { 54312 54313 // And clean up afterwards; thanks to no-block-scope, hidden can be referenced 54314 hidden.remove(); 54315 } 54316 if ( result !== undefined ) { 54317 return result; 54318 } 54319 return false; 54320 } 54321 return true; 54322 } 54323 54324 // Prevent submit for invalid forms or custom submit handlers 54325 if ( validator.cancelSubmit ) { 54326 validator.cancelSubmit = false; 54327 return handle(); 54328 } 54329 if ( validator.form() ) { 54330 if ( validator.pendingRequest ) { 54331 validator.formSubmitted = true; 54332 return false; 54333 } 54334 return handle(); 54335 } else { 54336 validator.focusInvalid(); 54337 return false; 54338 } 54339 } ); 54340 } 54341 54342 return validator; 54343 }, 54344 54345 // https://jqueryvalidation.org/valid/ 54346 valid: function() { 54347 var valid, validator, errorList; 54348 54349 if ( $( this[ 0 ] ).is( "form" ) ) { 54350 valid = this.validate().form(); 54351 } else { 54352 errorList = []; 54353 valid = true; 54354 validator = $( this[ 0 ].form ).validate(); 54355 this.each( function() { 54356 valid = validator.element( this ) && valid; 54357 if ( !valid ) { 54358 errorList = errorList.concat( validator.errorList ); 54359 } 54360 } ); 54361 validator.errorList = errorList; 54362 } 54363 return valid; 54364 }, 54365 54366 // https://jqueryvalidation.org/rules/ 54367 rules: function( command, argument ) { 54368 var element = this[ 0 ], 54369 isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false", 54370 settings, staticRules, existingRules, data, param, filtered; 54371 54372 // If nothing is selected, return empty object; can't chain anyway 54373 if ( element == null ) { 54374 return; 54375 } 54376 54377 if ( !element.form && isContentEditable ) { 54378 element.form = this.closest( "form" )[ 0 ]; 54379 element.name = this.attr( "name" ); 54380 } 54381 54382 if ( element.form == null ) { 54383 return; 54384 } 54385 54386 if ( command ) { 54387 settings = $.data( element.form, "validator" ).settings; 54388 staticRules = settings.rules; 54389 existingRules = $.validator.staticRules( element ); 54390 switch ( command ) { 54391 case "add": 54392 $.extend( existingRules, $.validator.normalizeRule( argument ) ); 54393 54394 // Remove messages from rules, but allow them to be set separately 54395 delete existingRules.messages; 54396 staticRules[ element.name ] = existingRules; 54397 if ( argument.messages ) { 54398 settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages ); 54399 } 54400 break; 54401 case "remove": 54402 if ( !argument ) { 54403 delete staticRules[ element.name ]; 54404 return existingRules; 54405 } 54406 filtered = {}; 54407 $.each( argument.split( /\s/ ), function( index, method ) { 54408 filtered[ method ] = existingRules[ method ]; 54409 delete existingRules[ method ]; 54410 } ); 54411 return filtered; 54412 } 54413 } 54414 54415 data = $.validator.normalizeRules( 54416 $.extend( 54417 {}, 54418 $.validator.classRules( element ), 54419 $.validator.attributeRules( element ), 54420 $.validator.dataRules( element ), 54421 $.validator.staticRules( element ) 54422 ), element ); 54423 54424 // Make sure required is at front 54425 if ( data.required ) { 54426 param = data.required; 54427 delete data.required; 54428 data = $.extend( { required: param }, data ); 54429 } 54430 54431 // Make sure remote is at back 54432 if ( data.remote ) { 54433 param = data.remote; 54434 delete data.remote; 54435 data = $.extend( data, { remote: param } ); 54436 } 54437 54438 return data; 54439 } 54440} ); 54441 54442// Custom selectors 54443$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support 54444 54445 // https://jqueryvalidation.org/blank-selector/ 54446 blank: function( a ) { 54447 return !$.trim( "" + $( a ).val() ); 54448 }, 54449 54450 // https://jqueryvalidation.org/filled-selector/ 54451 filled: function( a ) { 54452 var val = $( a ).val(); 54453 return val !== null && !!$.trim( "" + val ); 54454 }, 54455 54456 // https://jqueryvalidation.org/unchecked-selector/ 54457 unchecked: function( a ) { 54458 return !$( a ).prop( "checked" ); 54459 } 54460} ); 54461 54462// Constructor for validator 54463$.validator = function( options, form ) { 54464 this.settings = $.extend( true, {}, $.validator.defaults, options ); 54465 this.currentForm = form; 54466 this.init(); 54467}; 54468 54469// https://jqueryvalidation.org/jQuery.validator.format/ 54470$.validator.format = function( source, params ) { 54471 if ( arguments.length === 1 ) { 54472 return function() { 54473 var args = $.makeArray( arguments ); 54474 args.unshift( source ); 54475 return $.validator.format.apply( this, args ); 54476 }; 54477 } 54478 if ( params === undefined ) { 54479 return source; 54480 } 54481 if ( arguments.length > 2 && params.constructor !== Array ) { 54482 params = $.makeArray( arguments ).slice( 1 ); 54483 } 54484 if ( params.constructor !== Array ) { 54485 params = [ params ]; 54486 } 54487 $.each( params, function( i, n ) { 54488 source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() { 54489 return n; 54490 } ); 54491 } ); 54492 return source; 54493}; 54494 54495$.extend( $.validator, { 54496 54497 defaults: { 54498 messages: {}, 54499 groups: {}, 54500 rules: {}, 54501 errorClass: "error", 54502 pendingClass: "pending", 54503 validClass: "valid", 54504 errorElement: "label", 54505 focusCleanup: false, 54506 focusInvalid: true, 54507 errorContainer: $( [] ), 54508 errorLabelContainer: $( [] ), 54509 onsubmit: true, 54510 ignore: ":hidden", 54511 ignoreTitle: false
vendor: 5,102 bytes, lines 54511-54658
54511, 54512 onfocusin: function( element ) { 54513 this.lastActive = element; 54514 54515 // Hide error label and remove error class on focus if enabled 54516 if ( this.settings.focusCleanup ) { 54517 if ( this.settings.unhighlight ) { 54518 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 54519 } 54520 this.hideThese( this.errorsFor( element ) ); 54521 } 54522 }, 54523 onfocusout: function( element ) { 54524 if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { 54525 this.element( element ); 54526 } 54527 }, 54528 onkeyup: function( element, event ) { 54529 54530 // Avoid revalidate the field when pressing one of the following keys 54531 // Shift => 16 54532 // Ctrl => 17 54533 // Alt => 18 54534 // Caps lock => 20 54535 // End => 35 54536 // Home => 36 54537 // Left arrow => 37 54538 // Up arrow => 38 54539 // Right arrow => 39 54540 // Down arrow => 40 54541 // Insert => 45 54542 // Num lock => 144 54543 // AltGr key => 225 54544 var excludedKeys = [ 54545 16, 17, 18, 20, 35, 36, 37, 54546 38, 39, 40, 45, 144, 225 54547 ]; 54548 54549 if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { 54550 return; 54551 } else if ( element.name in this.submitted || element.name in this.invalid ) { 54552 this.element( element ); 54553 } 54554 }, 54555 onclick: function( element ) { 54556 54557 // Click on selects, radiobuttons and checkboxes 54558 if ( element.name in this.submitted ) { 54559 this.element( element ); 54560 54561 // Or option elements, check parent select in that case 54562 } else if ( element.parentNode.name in this.submitted ) { 54563 this.element( element.parentNode ); 54564 } 54565 }, 54566 highlight: function( element, errorClass, validClass ) { 54567 if ( element.type === "radio" ) { 54568 this.findByName( element.name ).addClass( errorClass ).removeClass( validClass ); 54569 } else { 54570 $( element ).addClass( errorClass ).removeClass( validClass ); 54571 } 54572 }, 54573 unhighlight: function( element, errorClass, validClass ) { 54574 if ( element.type === "radio" ) { 54575 this.findByName( element.name ).removeClass( errorClass ).addClass( validClass ); 54576 } else { 54577 $( element ).removeClass( errorClass ).addClass( validClass ); 54578 } 54579 } 54580 }, 54581 54582 // https://jqueryvalidation.org/jQuery.validator.setDefaults/ 54583 setDefaults: function( settings ) { 54584 $.extend( $.validator.defaults, settings ); 54585 }, 54586 54587 messages: { 54588 required: "This field is required.", 54589 remote: "Please fix this field.", 54590 email: "Please enter a valid email address.", 54591 url: "Please enter a valid URL.", 54592 date: "Please enter a valid date.", 54593 dateISO: "Please enter a valid date (ISO).", 54594 number: "Please enter a valid number.", 54595 digits: "Please enter only digits.", 54596 equalTo: "Please enter the same value again.", 54597 maxlength: $.validator.format( "Please enter no more than {0} characters." ), 54598 minlength: $.validator.format( "Please enter at least {0} characters." ), 54599 rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ), 54600 range: $.validator.format( "Please enter a value between {0} and {1}." ), 54601 max: $.validator.format( "Please enter a value less than or equal to {0}." ), 54602 min: $.validator.format( "Please enter a value greater than or equal to {0}." ), 54603 step: $.validator.format( "Please enter a multiple of {0}." ) 54604 }, 54605 54606 autoCreateRanges: false, 54607 54608 prototype: { 54609 54610 init: function() { 54611 this.labelContainer = $( this.settings.errorLabelContainer ); 54612 this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm ); 54613 this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer ); 54614 this.submitted = {}; 54615 this.valueCache = {}; 54616 this.pendingRequest = 0; 54617 this.pending = {}; 54618 this.invalid = {}; 54619 this.reset(); 54620 54621 var currentForm = this.currentForm, 54622 groups = ( this.groups = {} ), 54623 rules; 54624 $.each( this.settings.groups, function( key, value ) { 54625 if ( typeof value === "string" ) { 54626 value = value.split( /\s/ ); 54627 } 54628 $.each( value, function( index, name ) { 54629 groups[ name ] = key; 54630 } ); 54631 } ); 54632 rules = this.settings.rules; 54633 $.each( rules, function( key, value ) { 54634 rules[ key ] = $.validator.normalizeRule( value ); 54635 } ); 54636 54637 function delegate( event ) { 54638 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false"; 54639 54640 // Set form expando on contenteditable 54641 if ( !this.form && isContentEditable ) { 54642 this.form = $( this ).closest( "form" )[ 0 ]; 54643 this.name = $( this ).attr( "name" ); 54644 } 54645 54646 // Ignore the element if it belongs to another form. This will happen mainly 54647 // when setting the `form` attribute of an input to the id of another form. 54648 if ( currentForm !== this.form ) { 54649 return; 54650 } 54651 54652 var validator = $.data( this.form, "validator" ), 54653 eventType = "on" + event.type.replace( /^validate/, "" ), 54654 settings = validator.settings; 54655 if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) { 54656 settings[ eventType ].call( validator, this, event ); 54657 } 54658 }
vendor: 38,493 bytes, lines 54659-55903
54659 54660 $( this.currentForm ) 54661 .on( "focusin.validate focusout.validate keyup.validate", 54662 ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + 54663 "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + 54664 "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + 54665 "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate ) 54666 54667 // Support: Chrome, oldIE 54668 // "select" is provided as event.target when clicking a option 54669 .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate ); 54670 54671 if ( this.settings.invalidHandler ) { 54672 $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler ); 54673 } 54674 }, 54675 54676 // https://jqueryvalidation.org/Validator.form/ 54677 form: function() { 54678 this.checkForm(); 54679 $.extend( this.submitted, this.errorMap ); 54680 this.invalid = $.extend( {}, this.errorMap ); 54681 if ( !this.valid() ) { 54682 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); 54683 } 54684 this.showErrors(); 54685 return this.valid(); 54686 }, 54687 54688 checkForm: function() { 54689 this.prepareForm(); 54690 for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) { 54691 this.check( elements[ i ] ); 54692 } 54693 return this.valid(); 54694 }, 54695 54696 // https://jqueryvalidation.org/Validator.element/ 54697 element: function( element ) { 54698 var cleanElement = this.clean( element ), 54699 checkElement = this.validationTargetFor( cleanElement ), 54700 v = this, 54701 result = true, 54702 rs, group; 54703 54704 if ( checkElement === undefined ) { 54705 delete this.invalid[ cleanElement.name ]; 54706 } else { 54707 this.prepareElement( checkElement ); 54708 this.currentElements = $( checkElement ); 54709 54710 // If this element is grouped, then validate all group elements already 54711 // containing a value 54712 group = this.groups[ checkElement.name ]; 54713 if ( group ) { 54714 $.each( this.groups, function( name, testgroup ) { 54715 if ( testgroup === group && name !== checkElement.name ) { 54716 cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) ); 54717 if ( cleanElement && cleanElement.name in v.invalid ) { 54718 v.currentElements.push( cleanElement ); 54719 result = v.check( cleanElement ) && result; 54720 } 54721 } 54722 } ); 54723 } 54724 54725 rs = this.check( checkElement ) !== false; 54726 result = result && rs; 54727 if ( rs ) { 54728 this.invalid[ checkElement.name ] = false; 54729 } else { 54730 this.invalid[ checkElement.name ] = true; 54731 } 54732 54733 if ( !this.numberOfInvalids() ) { 54734 54735 // Hide error containers on last error 54736 this.toHide = this.toHide.add( this.containers ); 54737 } 54738 this.showErrors(); 54739 54740 // Add aria-invalid status for screen readers 54741 $( element ).attr( "aria-invalid", !rs ); 54742 } 54743 54744 return result; 54745 }, 54746 54747 // https://jqueryvalidation.org/Validator.showErrors/ 54748 showErrors: function( errors ) { 54749 if ( errors ) { 54750 var validator = this; 54751 54752 // Add items to error list and map 54753 $.extend( this.errorMap, errors ); 54754 this.errorList = $.map( this.errorMap, function( message, name ) { 54755 return { 54756 message: message, 54757 element: validator.findByName( name )[ 0 ] 54758 }; 54759 } ); 54760 54761 // Remove items from success list 54762 this.successList = $.grep( this.successList, function( element ) { 54763 return !( element.name in errors ); 54764 } ); 54765 } 54766 if ( this.settings.showErrors ) { 54767 this.settings.showErrors.call( this, this.errorMap, this.errorList ); 54768 } else { 54769 this.defaultShowErrors(); 54770 } 54771 }, 54772 54773 // https://jqueryvalidation.org/Validator.resetForm/ 54774 resetForm: function() { 54775 if ( $.fn.resetForm ) { 54776 $( this.currentForm ).resetForm(); 54777 } 54778 this.invalid = {}; 54779 this.submitted = {}; 54780 this.prepareForm(); 54781 this.hideErrors(); 54782 var elements = this.elements() 54783 .removeData( "previousValue" ) 54784 .removeAttr( "aria-invalid" ); 54785 54786 this.resetElements( elements ); 54787 }, 54788 54789 resetElements: function( elements ) { 54790 var i; 54791 54792 if ( this.settings.unhighlight ) { 54793 for ( i = 0; elements[ i ]; i++ ) { 54794 this.settings.unhighlight.call( this, elements[ i ], 54795 this.settings.errorClass, "" ); 54796 this.findByName( elements[ i ].name ).removeClass( this.settings.validClass ); 54797 } 54798 } else { 54799 elements 54800 .removeClass( this.settings.errorClass ) 54801 .removeClass( this.settings.validClass ); 54802 } 54803 }, 54804 54805 numberOfInvalids: function() { 54806 return this.objectLength( this.invalid ); 54807 }, 54808 54809 objectLength: function( obj ) { 54810 /* jshint unused: false */ 54811 var count = 0, 54812 i; 54813 for ( i in obj ) { 54814 54815 // This check allows counting elements with empty error 54816 // message as invalid elements 54817 if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) { 54818 count++; 54819 } 54820 } 54821 return count; 54822 }, 54823 54824 hideErrors: function() { 54825 this.hideThese( this.toHide ); 54826 }, 54827 54828 hideThese: function( errors ) { 54829 errors.not( this.containers ).text( "" ); 54830 this.addWrapper( errors ).hide(); 54831 }, 54832 54833 valid: function() { 54834 return this.size() === 0; 54835 }, 54836 54837 size: function() { 54838 return this.errorList.length; 54839 }, 54840 54841 focusInvalid: function() { 54842 if ( this.settings.focusInvalid ) { 54843 try { 54844 $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] ) 54845 .filter( ":visible" ) 54846 .focus() 54847 54848 // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 54849 .trigger( "focusin" ); 54850 } catch ( e ) { 54851 54852 // Ignore IE throwing errors when focusing hidden elements 54853 } 54854 } 54855 }, 54856 54857 findLastActive: function() { 54858 var lastActive = this.lastActive; 54859 return lastActive && $.grep( this.errorList, function( n ) { 54860 return n.element.name === lastActive.name; 54861 } ).length === 1 && lastActive; 54862 }, 54863 54864 elements: function() { 54865 var validator = this, 54866 rulesCache = {}; 54867 54868 // Select all valid inputs inside the form (no submit or reset buttons) 54869 return $( this.currentForm ) 54870 .find( "input, select, textarea, [contenteditable]" ) 54871 .not( ":submit, :reset, :image, :disabled" ) 54872 .not( this.settings.ignore ) 54873 .filter( function() { 54874 var name = this.name || $( this ).attr( "name" ); // For contenteditable 54875 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false"; 54876 54877 if ( !name && validator.settings.debug && window.console ) { 54878 console.error( "%o has no name assigned", this ); 54879 } 54880 54881 // Set form expando on contenteditable 54882 if ( isContentEditable ) { 54883 this.form = $( this ).closest( "form" )[ 0 ]; 54884 this.name = name; 54885 } 54886 54887 // Ignore elements that belong to other/nested forms 54888 if ( this.form !== validator.currentForm ) { 54889 return false; 54890 } 54891 54892 // Select only the first element for each name, and only those with rules specified 54893 if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { 54894 return false; 54895 } 54896 54897 rulesCache[ name ] = true; 54898 return true; 54899 } ); 54900 }, 54901 54902 clean: function( selector ) { 54903 return $( selector )[ 0 ]; 54904 }, 54905 54906 errors: function() { 54907 var errorClass = this.settings.errorClass.split( " " ).join( "." ); 54908 return $( this.settings.errorElement + "." + errorClass, this.errorContext ); 54909 }, 54910 54911 resetInternals: function() { 54912 this.successList = []; 54913 this.errorList = []; 54914 this.errorMap = {}; 54915 this.toShow = $( [] ); 54916 this.toHide = $( [] ); 54917 }, 54918 54919 reset: function() { 54920 this.resetInternals(); 54921 this.currentElements = $( [] ); 54922 }, 54923 54924 prepareForm: function() { 54925 this.reset(); 54926 this.toHide = this.errors().add( this.containers ); 54927 }, 54928 54929 prepareElement: function( element ) { 54930 this.reset(); 54931 this.toHide = this.errorsFor( element ); 54932 }, 54933 54934 elementValue: function( element ) { 54935 var $element = $( element ), 54936 type = element.type, 54937 isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false", 54938 val, idx; 54939 54940 if ( type === "radio" || type === "checkbox" ) { 54941 return this.findByName( element.name ).filter( ":checked" ).val(); 54942 } else if ( type === "number" && typeof element.validity !== "undefined" ) { 54943 return element.validity.badInput ? "NaN" : $element.val(); 54944 } 54945 54946 if ( isContentEditable ) { 54947 val = $element.text(); 54948 } else { 54949 val = $element.val(); 54950 } 54951 54952 if ( type === "file" ) { 54953 54954 // Modern browser (chrome & safari) 54955 if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) { 54956 return val.substr( 12 ); 54957 } 54958 54959 // Legacy browsers 54960 // Unix-based path 54961 idx = val.lastIndexOf( "/" ); 54962 if ( idx >= 0 ) { 54963 return val.substr( idx + 1 ); 54964 } 54965 54966 // Windows-based path 54967 idx = val.lastIndexOf( "\\" ); 54968 if ( idx >= 0 ) { 54969 return val.substr( idx + 1 ); 54970 } 54971 54972 // Just the file name 54973 return val; 54974 } 54975 54976 if ( typeof val === "string" ) { 54977 return val.replace( /\r/g, "" ); 54978 } 54979 return val; 54980 }, 54981 54982 check: function( element ) { 54983 element = this.validationTargetFor( this.clean( element ) ); 54984 54985 var rules = $( element ).rules(), 54986 rulesCount = $.map( rules, function( n, i ) { 54987 return i; 54988 } ).length, 54989 dependencyMismatch = false, 54990 val = this.elementValue( element ), 54991 result, method, rule, normalizer; 54992 54993 // Prioritize the local normalizer defined for this element over the global one 54994 // if the former exists, otherwise user the global one in case it exists. 54995 if ( typeof rules.normalizer === "function" ) { 54996 normalizer = rules.normalizer; 54997 } else if ( typeof this.settings.normalizer === "function" ) { 54998 normalizer = this.settings.normalizer; 54999 } 55000 55001 // If normalizer is defined, then call it to retreive the changed value instead 55002 // of using the real one. 55003 // Note that `this` in the normalizer is `element`. 55004 if ( normalizer ) { 55005 val = normalizer.call( element, val ); 55006 55007 // Delete the normalizer from rules to avoid treating it as a pre-defined method. 55008 delete rules.normalizer; 55009 } 55010 55011 for ( method in rules ) { 55012 rule = { method: method, parameters: rules[ method ] }; 55013 try { 55014 result = $.validator.methods[ method ].call( this, val, element, rule.parameters ); 55015 55016 // If a method indicates that the field is optional and therefore valid, 55017 // don't mark it as valid when there are no other rules 55018 if ( result === "dependency-mismatch" && rulesCount === 1 ) { 55019 dependencyMismatch = true; 55020 continue; 55021 } 55022 dependencyMismatch = false; 55023 55024 if ( result === "pending" ) { 55025 this.toHide = this.toHide.not( this.errorsFor( element ) ); 55026 return; 55027 } 55028 55029 if ( !result ) { 55030 this.formatAndAdd( element, rule ); 55031 return false; 55032 } 55033 } catch ( e ) { 55034 if ( this.settings.debug && window.console ) { 55035 console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); 55036 } 55037 if ( e instanceof TypeError ) { 55038 e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method."; 55039 } 55040 55041 throw e; 55042 } 55043 } 55044 if ( dependencyMismatch ) { 55045 return; 55046 } 55047 if ( this.objectLength( rules ) ) { 55048 this.successList.push( element ); 55049 } 55050 return true; 55051 }, 55052 55053 // Return the custom message for the given element and validation method 55054 // specified in the element's HTML5 data attribute 55055 // return the generic message if present and no method specific message is present 55056 customDataMessage: function( element, method ) { 55057 return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() + 55058 method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" ); 55059 }, 55060 55061 // Return the custom message for the given element name and validation method 55062 customMessage: function( name, method ) { 55063 var m = this.settings.messages[ name ]; 55064 return m && ( m.constructor === String ? m : m[ method ] ); 55065 }, 55066 55067 // Return the first defined argument, allowing empty strings 55068 findDefined: function() { 55069 for ( var i = 0; i < arguments.length; i++ ) { 55070 if ( arguments[ i ] !== undefined ) { 55071 return arguments[ i ]; 55072 } 55073 } 55074 return undefined; 55075 }, 55076 55077 // The second parameter 'rule' used to be a string, and extended to an object literal 55078 // of the following form: 55079 // rule = { 55080 // method: "method name", 55081 // parameters: "the given method parameters" 55082 // } 55083 // 55084 // The old behavior still supported, kept to maintain backward compatibility with 55085 // old code, and will be removed in the next major release. 55086 defaultMessage: function( element, rule ) { 55087 if ( typeof rule === "string" ) { 55088 rule = { method: rule }; 55089 } 55090 55091 var message = this.findDefined( 55092 this.customMessage( element.name, rule.method ), 55093 this.customDataMessage( element, rule.method ), 55094 55095 // 'title' is never undefined, so handle empty string as undefined 55096 !this.settings.ignoreTitle && element.title || undefined, 55097 $.validator.messages[ rule.method ], 55098 "<strong>Warning: No message defined for " + element.name + "</strong>" 55099 ), 55100 theregex = /\$?\{(\d+)\}/g; 55101 if ( typeof message === "function" ) { 55102 message = message.call( this, rule.parameters, element ); 55103 } else if ( theregex.test( message ) ) { 55104 message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters ); 55105 } 55106 55107 return message; 55108 }, 55109 55110 formatAndAdd: function( element, rule ) { 55111 var message = this.defaultMessage( element, rule ); 55112 55113 this.errorList.push( { 55114 message: message, 55115 element: element, 55116 method: rule.method 55117 } ); 55118 55119 this.errorMap[ element.name ] = message; 55120 this.submitted[ element.name ] = message; 55121 }, 55122 55123 addWrapper: function( toToggle ) { 55124 if ( this.settings.wrapper ) { 55125 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 55126 } 55127 return toToggle; 55128 }, 55129 55130 defaultShowErrors: function() { 55131 var i, elements, error; 55132 for ( i = 0; this.errorList[ i ]; i++ ) { 55133 error = this.errorList[ i ]; 55134 if ( this.settings.highlight ) { 55135 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); 55136 } 55137 this.showLabel( error.element, error.message ); 55138 } 55139 if ( this.errorList.length ) { 55140 this.toShow = this.toShow.add( this.containers ); 55141 } 55142 if ( this.settings.success ) { 55143 for ( i = 0; this.successList[ i ]; i++ ) { 55144 this.showLabel( this.successList[ i ] ); 55145 } 55146 } 55147 if ( this.settings.unhighlight ) { 55148 for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) { 55149 this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass ); 55150 } 55151 } 55152 this.toHide = this.toHide.not( this.toShow ); 55153 this.hideErrors(); 55154 this.addWrapper( this.toShow ).show(); 55155 }, 55156 55157 validElements: function() { 55158 return this.currentElements.not( this.invalidElements() ); 55159 }, 55160 55161 invalidElements: function() { 55162 return $( this.errorList ).map( function() { 55163 return this.element; 55164 } ); 55165 }, 55166 55167 showLabel: function( element, message ) { 55168 var place, group, errorID, v, 55169 error = this.errorsFor( element ), 55170 elementID = this.idOrName( element ), 55171 describedBy = $( element ).attr( "aria-describedby" ); 55172 55173 if ( error.length ) { 55174 55175 // Refresh error/success class 55176 error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 55177 55178 // Replace message on existing label 55179 error.html( message ); 55180 } else { 55181 55182 // Create error element 55183 error = $( "<" + this.settings.errorElement + ">" ) 55184 .attr( "id", elementID + "-error" ) 55185 .addClass( this.settings.errorClass ) 55186 .html( message || "" ); 55187 55188 // Maintain reference to the element to be placed into the DOM 55189 place = error; 55190 if ( this.settings.wrapper ) { 55191 55192 // Make sure the element is visible, even in IE 55193 // actually showing the wrapped element is handled elsewhere 55194 place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent(); 55195 } 55196 if ( this.labelContainer.length ) { 55197 this.labelContainer.append( place ); 55198 } else if ( this.settings.errorPlacement ) { 55199 this.settings.errorPlacement.call( this, place, $( element ) ); 55200 } else { 55201 place.insertAfter( element ); 55202 } 55203 55204 // Link error back to the element 55205 if ( error.is( "label" ) ) { 55206 55207 // If the error is a label, then associate using 'for' 55208 error.attr( "for", elementID ); 55209 55210 // If the element is not a child of an associated label, then it's necessary 55211 // to explicitly apply aria-describedby 55212 } else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) { 55213 errorID = error.attr( "id" ); 55214 55215 // Respect existing non-error aria-describedby 55216 if ( !describedBy ) { 55217 describedBy = errorID; 55218 } else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) { 55219 55220 // Add to end of list if not already present 55221 describedBy += " " + errorID; 55222 } 55223 $( element ).attr( "aria-describedby", describedBy ); 55224 55225 // If this element is grouped, then assign to all elements in the same group 55226 group = this.groups[ element.name ]; 55227 if ( group ) { 55228 v = this; 55229 $.each( v.groups, function( name, testgroup ) { 55230 if ( testgroup === group ) { 55231 $( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm ) 55232 .attr( "aria-describedby", error.attr( "id" ) ); 55233 } 55234 } ); 55235 } 55236 } 55237 } 55238 if ( !message && this.settings.success ) { 55239 error.text( "" ); 55240 if ( typeof this.settings.success === "string" ) { 55241 error.addClass( this.settings.success ); 55242 } else { 55243 this.settings.success( error, element ); 55244 } 55245 } 55246 this.toShow = this.toShow.add( error ); 55247 }, 55248 55249 errorsFor: function( element ) { 55250 var name = this.escapeCssMeta( this.idOrName( element ) ), 55251 describer = $( element ).attr( "aria-describedby" ), 55252 selector = "label[for='" + name + "'], label[for='" + name + "'] *"; 55253 55254 // 'aria-describedby' should directly reference the error element 55255 if ( describer ) { 55256 selector = selector + ", #" + this.escapeCssMeta( describer ) 55257 .replace( /\s+/g, ", #" ); 55258 } 55259 55260 return this 55261 .errors() 55262 .filter( selector ); 55263 }, 55264 55265 // See https://api.jquery.com/category/selectors/, for CSS 55266 // meta-characters that should be escaped in order to be used with JQuery 55267 // as a literal part of a name/id or any selector. 55268 escapeCssMeta: function( string ) { 55269 return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" ); 55270 }, 55271 55272 idOrName: function( element ) { 55273 return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name ); 55274 }, 55275 55276 validationTargetFor: function( element ) { 55277 55278 // If radio/checkbox, validate first element in group instead 55279 if ( this.checkable( element ) ) { 55280 element = this.findByName( element.name ); 55281 } 55282 55283 // Always apply ignore filter 55284 return $( element ).not( this.settings.ignore )[ 0 ]; 55285 }, 55286 55287 checkable: function( element ) { 55288 return ( /radio|checkbox/i ).test( element.type ); 55289 }, 55290 55291 findByName: function( name ) { 55292 return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" ); 55293 }, 55294 55295 getLength: function( value, element ) { 55296 switch ( element.nodeName.toLowerCase() ) { 55297 case "select": 55298 return $( "option:selected", element ).length; 55299 case "input": 55300 if ( this.checkable( element ) ) { 55301 return this.findByName( element.name ).filter( ":checked" ).length; 55302 } 55303 } 55304 return value.length; 55305 }, 55306 55307 depend: function( param, element ) { 55308 return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true; 55309 }, 55310 55311 dependTypes: { 55312 "boolean": function( param ) { 55313 return param; 55314 }, 55315 "string": function( param, element ) { 55316 return !!$( param, element.form ).length; 55317 }, 55318 "function": function( param, element ) { 55319 return param( element ); 55320 } 55321 }, 55322 55323 optional: function( element ) { 55324 var val = this.elementValue( element ); 55325 return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch"; 55326 }, 55327 55328 startRequest: function( element ) { 55329 if ( !this.pending[ element.name ] ) { 55330 this.pendingRequest++; 55331 $( element ).addClass( this.settings.pendingClass ); 55332 this.pending[ element.name ] = true; 55333 } 55334 }, 55335 55336 stopRequest: function( element, valid ) { 55337 this.pendingRequest--; 55338 55339 // Sometimes synchronization fails, make sure pendingRequest is never < 0 55340 if ( this.pendingRequest < 0 ) { 55341 this.pendingRequest = 0; 55342 } 55343 delete this.pending[ element.name ]; 55344 $( element ).removeClass( this.settings.pendingClass ); 55345 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { 55346 $( this.currentForm ).submit(); 55347 55348 // Remove the hidden input that was used as a replacement for the 55349 // missing submit button. The hidden input is added by `handle()` 55350 // to ensure that the value of the used submit button is passed on 55351 // for scripted submits triggered by this method 55352 if ( this.submitButton ) { 55353 $( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove(); 55354 } 55355 55356 this.formSubmitted = false; 55357 } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) { 55358 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); 55359 this.formSubmitted = false; 55360 } 55361 }, 55362 55363 previousValue: function( element, method ) { 55364 method = typeof method === "string" && method || "remote"; 55365 55366 return $.data( element, "previousValue" ) || $.data( element, "previousValue", { 55367 old: null, 55368 valid: true, 55369 message: this.defaultMessage( element, { method: method } ) 55370 } ); 55371 }, 55372 55373 // Cleans up all forms and elements, removes validator-specific events 55374 destroy: function() { 55375 this.resetForm(); 55376 55377 $( this.currentForm ) 55378 .off( ".validate" ) 55379 .removeData( "validator" ) 55380 .find( ".validate-equalTo-blur" ) 55381 .off( ".validate-equalTo" ) 55382 .removeClass( "validate-equalTo-blur" ) 55383 .find( ".validate-lessThan-blur" ) 55384 .off( ".validate-lessThan" ) 55385 .removeClass( "validate-lessThan-blur" ) 55386 .find( ".validate-lessThanEqual-blur" ) 55387 .off( ".validate-lessThanEqual" ) 55388 .removeClass( "validate-lessThanEqual-blur" ) 55389 .find( ".validate-greaterThanEqual-blur" ) 55390 .off( ".validate-greaterThanEqual" ) 55391 .removeClass( "validate-greaterThanEqual-blur" ) 55392 .find( ".validate-greaterThan-blur" ) 55393 .off( ".validate-greaterThan" ) 55394 .removeClass( "validate-greaterThan-blur" ); 55395 } 55396 55397 }, 55398 55399 classRuleSettings: { 55400 required: { required: true }, 55401 email: { email: true }, 55402 url: { url: true }, 55403 date: { date: true }, 55404 dateISO: { dateISO: true }, 55405 number: { number: true }, 55406 digits: { digits: true }, 55407 creditcard: { creditcard: true } 55408 }, 55409 55410 addClassRules: function( className, rules ) { 55411 if ( className.constructor === String ) { 55412 this.classRuleSettings[ className ] = rules; 55413 } else { 55414 $.extend( this.classRuleSettings, className ); 55415 } 55416 }, 55417 55418 classRules: function( element ) { 55419 var rules = {}, 55420 classes = $( element ).attr( "class" ); 55421 55422 if ( classes ) { 55423 $.each( classes.split( " " ), function() { 55424 if ( this in $.validator.classRuleSettings ) { 55425 $.extend( rules, $.validator.classRuleSettings[ this ] ); 55426 } 55427 } ); 55428 } 55429 return rules; 55430 }, 55431 55432 normalizeAttributeRule: function( rules, type, method, value ) { 55433 55434 // Convert the value to a number for number inputs, and for text for backwards compability 55435 // allows type="date" and others to be compared as strings 55436 if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { 55437 value = Number( value ); 55438 55439 // Support Opera Mini, which returns NaN for undefined minlength 55440 if ( isNaN( value ) ) { 55441 value = undefined; 55442 } 55443 } 55444 55445 if ( value || value === 0 ) { 55446 rules[ method ] = value; 55447 } else if ( type === method && type !== "range" ) { 55448 55449 // Exception: the jquery validate 'range' method 55450 // does not test for the html5 'range' type 55451 rules[ method ] = true; 55452 } 55453 }, 55454 55455 attributeRules: function( element ) { 55456 var rules = {}, 55457 $element = $( element ), 55458 type = element.getAttribute( "type" ), 55459 method, value; 55460 55461 for ( method in $.validator.methods ) { 55462 55463 // Support for <input required> in both html5 and older browsers 55464 if ( method === "required" ) { 55465 value = element.getAttribute( method ); 55466 55467 // Some browsers return an empty string for the required attribute 55468 // and non-HTML5 browsers might have required="" markup 55469 if ( value === "" ) { 55470 value = true; 55471 } 55472 55473 // Force non-HTML5 browsers to return bool 55474 value = !!value; 55475 } else { 55476 value = $element.attr( method ); 55477 } 55478 55479 this.normalizeAttributeRule( rules, type, method, value ); 55480 } 55481 55482 // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs 55483 if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) { 55484 delete rules.maxlength; 55485 } 55486 55487 return rules; 55488 }, 55489 55490 dataRules: function( element ) { 55491 var rules = {}, 55492 $element = $( element ), 55493 type = element.getAttribute( "type" ), 55494 method, value; 55495 55496 for ( method in $.validator.methods ) { 55497 value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() ); 55498 55499 // Cast empty attributes like `data-rule-required` to `true` 55500 if ( value === "" ) { 55501 value = true; 55502 } 55503 55504 this.normalizeAttributeRule( rules, type, method, value ); 55505 } 55506 return rules; 55507 }, 55508 55509 staticRules: function( element ) { 55510 var rules = {}, 55511 validator = $.data( element.form, "validator" ); 55512 55513 if ( validator.settings.rules ) { 55514 rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {}; 55515 } 55516 return rules; 55517 }, 55518 55519 normalizeRules: function( rules, element ) { 55520 55521 // Handle dependency check 55522 $.each( rules, function( prop, val ) { 55523 55524 // Ignore rule when param is explicitly false, eg. required:false 55525 if ( val === false ) { 55526 delete rules[ prop ]; 55527 return; 55528 } 55529 if ( val.param || val.depends ) { 55530 var keepRule = true; 55531 switch ( typeof val.depends ) { 55532 case "string": 55533 keepRule = !!$( val.depends, element.form ).length; 55534 break; 55535 case "function": 55536 keepRule = val.depends.call( element, element ); 55537 break; 55538 } 55539 if ( keepRule ) { 55540 rules[ prop ] = val.param !== undefined ? val.param : true; 55541 } else { 55542 $.data( element.form, "validator" ).resetElements( $( element ) ); 55543 delete rules[ prop ]; 55544 } 55545 } 55546 } ); 55547 55548 // Evaluate parameters 55549 $.each( rules, function( rule, parameter ) { 55550 rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter; 55551 } ); 55552 55553 // Clean number parameters 55554 $.each( [ "minlength", "maxlength" ], function() { 55555 if ( rules[ this ] ) { 55556 rules[ this ] = Number( rules[ this ] ); 55557 } 55558 } ); 55559 $.each( [ "rangelength", "range" ], function() { 55560 var parts; 55561 if ( rules[ this ] ) { 55562 if ( $.isArray( rules[ this ] ) ) { 55563 rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ]; 55564 } else if ( typeof rules[ this ] === "string" ) { 55565 parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ ); 55566 rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ]; 55567 } 55568 } 55569 } ); 55570 55571 if ( $.validator.autoCreateRanges ) { 55572 55573 // Auto-create ranges 55574 if ( rules.min != null && rules.max != null ) { 55575 rules.range = [ rules.min, rules.max ]; 55576 delete rules.min; 55577 delete rules.max; 55578 } 55579 if ( rules.minlength != null && rules.maxlength != null ) { 55580 rules.rangelength = [ rules.minlength, rules.maxlength ]; 55581 delete rules.minlength; 55582 delete rules.maxlength; 55583 } 55584 } 55585 55586 return rules; 55587 }, 55588 55589 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 55590 normalizeRule: function( data ) { 55591 if ( typeof data === "string" ) { 55592 var transformed = {}; 55593 $.each( data.split( /\s/ ), function() { 55594 transformed[ this ] = true; 55595 } ); 55596 data = transformed; 55597 } 55598 return data; 55599 }, 55600 55601 // https://jqueryvalidation.org/jQuery.validator.addMethod/ 55602 addMethod: function( name, method, message ) { 55603 $.validator.methods[ name ] = method; 55604 $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ]; 55605 if ( method.length < 3 ) { 55606 $.validator.addClassRules( name, $.validator.normalizeRule( name ) ); 55607 } 55608 }, 55609 55610 // https://jqueryvalidation.org/jQuery.validator.methods/ 55611 methods: { 55612 55613 // https://jqueryvalidation.org/required-method/ 55614 required: function( value, element, param ) { 55615 55616 // Check if dependency is met 55617 if ( !this.depend( param, element ) ) { 55618 return "dependency-mismatch"; 55619 } 55620 if ( element.nodeName.toLowerCase() === "select" ) { 55621 55622 // Could be an array for select-multiple or a string, both are fine this way 55623 var val = $( element ).val(); 55624 return val && val.length > 0; 55625 } 55626 if ( this.checkable( element ) ) { 55627 return this.getLength( value, element ) > 0; 55628 } 55629 return value !== undefined && value !== null && value.length > 0; 55630 }, 55631 55632 // https://jqueryvalidation.org/email-method/ 55633 email: function( value, element ) { 55634 55635 // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address 55636 // Retrieved 2014-01-14 55637 // If you have a problem with this implementation, report a bug against the above spec 55638 // Or use custom methods to implement your own email validation 55639 return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value ); 55640 }, 55641 55642 // https://jqueryvalidation.org/url-method/ 55643 url: function( value, element ) { 55644 55645 // Copyright (c) 2010-2013 Diego Perini, MIT licensed 55646 // https://gist.github.com/dperini/729294 55647 // see also https://mathiasbynens.be/demo/url-regex 55648 // modified to allow protocol-relative URLs 55649 return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ); 55650 }, 55651 55652 // https://jqueryvalidation.org/date-method/ 55653 date: ( function() { 55654 var called = false; 55655 55656 return function( value, element ) { 55657 if ( !called ) { 55658 called = true; 55659 if ( this.settings.debug && window.console ) { 55660 console.warn( 55661 "The `date` method is deprecated and will be removed in version '2.0.0'.\n" + 55662 "Please don't use it, since it relies on the Date constructor, which\n" + 55663 "behaves very differently across browsers and locales. Use `dateISO`\n" + 55664 "instead or one of the locale specific methods in `localizations/`\n" + 55665 "and `additional-methods.js`." 55666 ); 55667 } 55668 } 55669 55670 return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() ); 55671 }; 55672 }() ), 55673 55674 // https://jqueryvalidation.org/dateISO-method/ 55675 dateISO: function( value, element ) { 55676 return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ); 55677 }, 55678 55679 // https://jqueryvalidation.org/number-method/ 55680 number: function( value, element ) { 55681 return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value ); 55682 }, 55683 55684 // https://jqueryvalidation.org/digits-method/ 55685 digits: function( value, element ) { 55686 return this.optional( element ) || /^\d+$/.test( value ); 55687 }, 55688 55689 // https://jqueryvalidation.org/minlength-method/ 55690 minlength: function( value, element, param ) { 55691 var length = $.isArray( value ) ? value.length : this.getLength( value, element ); 55692 return this.optional( element ) || length >= param; 55693 }, 55694 55695 // https://jqueryvalidation.org/maxlength-method/ 55696 maxlength: function( value, element, param ) { 55697 var length = $.isArray( value ) ? value.length : this.getLength( value, element ); 55698 return this.optional( element ) || length <= param; 55699 }, 55700 55701 // https://jqueryvalidation.org/rangelength-method/ 55702 rangelength: function( value, element, param ) { 55703 var length = $.isArray( value ) ? value.length : this.getLength( value, element ); 55704 return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] ); 55705 }, 55706 55707 // https://jqueryvalidation.org/min-method/ 55708 min: function( value, element, param ) { 55709 return this.optional( element ) || value >= param; 55710 }, 55711 55712 // https://jqueryvalidation.org/max-method/ 55713 max: function( value, element, param ) { 55714 return this.optional( element ) || value <= param; 55715 }, 55716 55717 // https://jqueryvalidation.org/range-method/ 55718 range: function( value, element, param ) { 55719 return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] ); 55720 }, 55721 55722 // https://jqueryvalidation.org/step-method/ 55723 step: function( value, element, param ) { 55724 var type = $( element ).attr( "type" ), 55725 errorMessage = "Step attribute on input type " + type + " is not supported.", 55726 supportedTypes = [ "text", "number", "range" ], 55727 re = new RegExp( "\\b" + type + "\\b" ), 55728 notSupported = type && !re.test( supportedTypes.join() ), 55729 decimalPlaces = function( num ) { 55730 var match = ( "" + num ).match( /(?:\.(\d+))?$/ ); 55731 if ( !match ) { 55732 return 0; 55733 } 55734 55735 // Number of digits right of decimal point. 55736 return match[ 1 ] ? match[ 1 ].length : 0; 55737 }, 55738 toInt = function( num ) { 55739 return Math.round( num * Math.pow( 10, decimals ) ); 55740 }, 55741 valid = true, 55742 decimals; 55743 55744 // Works only for text, number and range input types 55745 // TODO find a way to support input types date, datetime, datetime-local, month, time and week 55746 if ( notSupported ) { 55747 throw new Error( errorMessage ); 55748 } 55749 55750 decimals = decimalPlaces( param ); 55751 55752 // Value can't have too many decimals 55753 if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) { 55754 valid = false; 55755 } 55756 55757 return this.optional( element ) || valid; 55758 }, 55759 55760 // https://jqueryvalidation.org/equalTo-method/ 55761 equalTo: function( value, element, param ) { 55762 55763 // Bind to the blur event of the target in order to revalidate whenever the target field is updated 55764 var target = $( param ); 55765 if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) { 55766 target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() { 55767 $( element ).valid(); 55768 } ); 55769 } 55770 return value === target.val(); 55771 }, 55772 55773 // https://jqueryvalidation.org/remote-method/ 55774 remote: function( value, element, param, method ) { 55775 if ( this.optional( element ) ) { 55776 return "dependency-mismatch"; 55777 } 55778 55779 method = typeof method === "string" && method || "remote"; 55780 55781 var previous = this.previousValue( element, method ), 55782 validator, data, optionDataString; 55783 55784 if ( !this.settings.messages[ element.name ] ) { 55785 this.settings.messages[ element.name ] = {}; 55786 } 55787 previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ]; 55788 this.settings.messages[ element.name ][ method ] = previous.message; 55789 55790 param = typeof param === "string" && { url: param } || param; 55791 optionDataString = $.param( $.extend( { data: value }, param.data ) ); 55792 if ( previous.old === optionDataString ) { 55793 return previous.valid; 55794 } 55795 55796 previous.old = optionDataString; 55797 validator = this; 55798 this.startRequest( element ); 55799 data = {}; 55800 data[ element.name ] = value; 55801 $.ajax( $.extend( true, { 55802 mode: "abort", 55803 port: "validate" + element.name, 55804 dataType: "json", 55805 data: data, 55806 context: validator.currentForm, 55807 success: function( response ) { 55808 var valid = response === true || response === "true", 55809 errors, message, submitted; 55810 55811 validator.settings.messages[ element.name ][ method ] = previous.originalMessage; 55812 if ( valid ) { 55813 submitted = validator.formSubmitted; 55814 validator.resetInternals(); 55815 validator.toHide = validator.errorsFor( element ); 55816 validator.formSubmitted = submitted; 55817 validator.successList.push( element ); 55818 validator.invalid[ element.name ] = false; 55819 validator.showErrors(); 55820 } else { 55821 errors = {}; 55822 message = response || validator.defaultMessage( element, { method: method, parameters: value } ); 55823 errors[ element.name ] = previous.message = message; 55824 validator.invalid[ element.name ] = true; 55825 validator.showErrors( errors ); 55826 } 55827 previous.valid = valid; 55828 validator.stopRequest( element, valid ); 55829 } 55830 }, param ) ); 55831 return "pending"; 55832 } 55833 } 55834 55835} ); 55836 55837// Ajax mode: abort 55838// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 55839// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 55840 55841var pendingRequests = {}, 55842 ajax; 55843 55844// Use a prefilter if available (1.5+) 55845if ( $.ajaxPrefilter ) { 55846 $.ajaxPrefilter( function( settings, _, xhr ) { 55847 var port = settings.port; 55848 if ( settings.mode === "abort" ) { 55849 if ( pendingRequests[ port ] ) { 55850 pendingRequests[ port ].abort(); 55851 } 55852 pendingRequests[ port ] = xhr; 55853 } 55854 } ); 55855} else { 55856 55857 // Proxy ajax 55858 ajax = $.ajax; 55859 $.ajax = function( settings ) { 55860 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 55861 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 55862 if ( mode === "abort" ) { 55863 if ( pendingRequests[ port ] ) { 55864 pendingRequests[ port ].abort(); 55865 } 55866 pendingRequests[ port ] = ajax.apply( this, arguments ); 55867 return pendingRequests[ port ]; 55868 } 55869 return ajax.apply( this, arguments ); 55870 }; 55871} 55872return $; 55873})); 55874/*! 55875 * jQuery Validation Plugin v1.19.0 55876 * 55877 * https://jqueryvalidation.org/ 55878 * 55879 * Copyright (c) 2018 Jörn Zaefferer 55880 * Released under the MIT license 55881 */ 55882(function( factory ) { 55883 if ( typeof define === "function" && define.amd ) { 55884 define( ["jquery", "./jquery.validate"], factory ); 55885 } else if (typeof module === "object" && module.exports) { 55886 module.exports = factory( require( "jquery" ) ); 55887 } else { 55888 factory( jQuery ); 55889 } 55890}(function( $ ) { 55891 55892( function() { 55893 55894 function stripHtml( value ) { 55895 55896 // Remove html tags and space chars 55897 return value.replace( /<.[^<>]*?>/g, " " ).replace( / | /gi, " " ) 55898 55899 // Remove punctuation 55900 .replace( /[.(),;:!?%#$'\"_+=\/\-âââ]*/g, "" ); 55901 } 55902 55903 $.validator.addMethod( "maxWords", function( value, element, params ) {
vendor: 4,581 bytes, lines 55904-56036
55904 return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length <= params; 55905 }, $.validator.format( "Please enter {0} words or less." ) ); 55906 55907 $.validator.addMethod( "minWords", function( value, element, params ) { 55908 return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length >= params; 55909 }, $.validator.format( "Please enter at least {0} words." ) ); 55910 55911 $.validator.addMethod( "rangeWords", function( value, element, params ) { 55912 var valueStripped = stripHtml( value ), 55913 regex = /\b\w+\b/g; 55914 return this.optional( element ) || valueStripped.match( regex ).length >= params[ 0 ] && valueStripped.match( regex ).length <= params[ 1 ]; 55915 }, $.validator.format( "Please enter between {0} and {1} words." ) ); 55916 55917}() ); 55918 55919/** 55920 * This is used in the United States to process payments, deposits, 55921 * or transfers using the Automated Clearing House (ACH) or Fedwire 55922 * systems. A very common use case would be to validate a form for 55923 * an ACH bill payment. 55924 */ 55925$.validator.addMethod( "abaRoutingNumber", function( value ) { 55926 var checksum = 0; 55927 var tokens = value.split( "" ); 55928 var length = tokens.length; 55929 55930 // Length Check 55931 if ( length !== 9 ) { 55932 return false; 55933 } 55934 55935 // Calc the checksum 55936 // https://en.wikipedia.org/wiki/ABA_routing_transit_number 55937 for ( var i = 0; i < length; i += 3 ) { 55938 checksum += parseInt( tokens[ i ], 10 ) * 3 + 55939 parseInt( tokens[ i + 1 ], 10 ) * 7 + 55940 parseInt( tokens[ i + 2 ], 10 ); 55941 } 55942 55943 // If not zero and divisible by 10 then valid 55944 if ( checksum !== 0 && checksum % 10 === 0 ) { 55945 return true; 55946 } 55947 55948 return false; 55949}, "Please enter a valid routing number." ); 55950 55951// Accept a value from a file input based on a required mimetype 55952$.validator.addMethod( "accept", function( value, element, param ) { 55953 55954 // Split mime on commas in case we have multiple types we can accept 55955 var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*", 55956 optionalValue = this.optional( element ), 55957 i, file, regex; 55958 55959 // Element is optional 55960 if ( optionalValue ) { 55961 return optionalValue; 55962 } 55963 55964 if ( $( element ).attr( "type" ) === "file" ) { 55965 55966 // Escape string to be used in the regex 55967 // see: https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex 55968 // Escape also "/*" as "/.*" as a wildcard 55969 typeParam = typeParam 55970 .replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" ) 55971 .replace( /,/g, "|" ) 55972 .replace( /\/\*/g, "/.*" ); 55973 55974 // Check if the element has a FileList before checking each file 55975 if ( element.files && element.files.length ) { 55976 regex = new RegExp( ".?(" + typeParam + ")$", "i" ); 55977 for ( i = 0; i < element.files.length; i++ ) { 55978 file = element.files[ i ]; 55979 55980 // Grab the mimetype from the loaded file, verify it matches 55981 if ( !file.type.match( regex ) ) { 55982 return false; 55983 } 55984 } 55985 } 55986 } 55987 55988 // Either return true because we've validated each file, or because the 55989 // browser does not support element.files and the FileList feature 55990 return true; 55991}, $.validator.format( "Please enter a value with a valid mimetype." ) ); 55992 55993$.validator.addMethod( "alphanumeric", function( value, element ) { 55994 return this.optional( element ) || /^\w+$/i.test( value ); 55995}, "Letters, numbers, and underscores only please" ); 55996 55997/* 55998 * Dutch bank account numbers (not 'giro' numbers) have 9 digits 55999 * and pass the '11 check'. 56000 * We accept the notation with spaces, as that is common. 56001 * acceptable: 123456789 or 12 34 56 789 56002 */ 56003$.validator.addMethod( "bankaccountNL", function( value, element ) { 56004 if ( this.optional( element ) ) { 56005 return true; 56006 } 56007 if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) { 56008 return false; 56009 } 56010 56011 // Now '11 check' 56012 var account = value.replace( / /g, "" ), // Remove spaces 56013 sum = 0, 56014 len = account.length, 56015 pos, factor, digit; 56016 for ( pos = 0; pos < len; pos++ ) { 56017 factor = len - pos; 56018 digit = account.substring( pos, pos + 1 ); 56019 sum = sum + factor * digit; 56020 } 56021 return sum % 11 === 0; 56022}, "Please specify a valid bank account number" ); 56023 56024$.validator.addMethod( "bankorgiroaccountNL", function( value, element ) { 56025 return this.optional( element ) || 56026 ( $.validator.methods.bankaccountNL.call( this, value, element ) ) || 56027 ( $.validator.methods.giroaccountNL.call( this, value, element ) ); 56028}, "Please specify a valid bank or giro account number" ); 56029 56030/** 56031 * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity. 56032 * 56033 * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional) 56034 * 56035 * Validation is case-insensitive. Please make sure to normalize input yourself. 56036 *
56037 * BIC definition in detail: 56038 * - First 4 characters - bank code (only letters) 56039 * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters) 56040 * - Next 2 characters - location code (letters and digits) 56041 * a. shall not start with '0' or '1' 56042 * b. second character must be a letter ('O' is not allowed) or digit ('0' for test (therefore not allowed), '1' denoting passive participant, '2' typically reverse-billing) 56043 * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits) 56044 */ 56045$.validator.addMethod( "bic", function( value, element ) { 56046 return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() ); 56047}, "Please specify a valid BIC code" ); 56048 56049/* 56050 * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities 56051 * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal 56052 * 56053 * Spanish CIF structure: 56054 * 56055 * [ T ][ P ][ P ][ N ][ N ][ N ][ N ][ N ][ C ] 56056 * 56057 * Where: 56058 * 56059 * T: 1 character. Kind of Organization Letter: [ABCDEFGHJKLMNPQRSUVW] 56060 * P: 2 characters. Province. 56061 * N: 5 characters. Secuencial Number within the province. 56062 * C: 1 character. Control Digit: [0-9A-J]. 56063 * 56064 * [ T ]: Kind of Organizations. Possible values: 56065 * 56066 * A. Corporations 56067 * B. LLCs 56068 * C. General partnerships 56069 * D. Companies limited partnerships 56070 * E. Communities of goods 56071 * F. Cooperative Societies 56072 * G. Associations 56073 * H. Communities of homeowners in horizontal property regime 56074 * J. Civil Societies 56075 * K. Old format 56076 * L. Old format 56077 * M. Old format 56078 * N. Nonresident entities 56079 * P. Local authorities 56080 * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions 56081 * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008) 56082 * S. Organs of State Administration and regions 56083 * V. Agrarian Transformation 56084 * W. Permanent establishments of non-resident in Spain 56085 * 56086 * [ C ]: Control Digit. It can be a number or a letter depending on T value: 56087 * [ T ] --> [ C ] 56088 * ------ ---------- 56089 * A Number 56090 * B Number 56091 * E Number 56092 * H Number 56093 * K Letter 56094 * P Letter 56095 * Q Letter 56096 * S Letter 56097 * 56098 */ 56099$.validator.addMethod( "cifES", function( value, element ) { 56100 "use strict"; 56101 56102 if ( this.optional( element ) ) { 56103 return true; 56104 } 56105 56106 var cifRegEx = new RegExp( /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi ); 56107 var letter = value.substring( 0, 1 ), // [ T ] 56108 number = value.substring( 1, 8 ), // [ P ][ P ][ N ][ N ][ N ][ N ][ N ] 56109 control = value.substring( 8, 9 ), // [ C ] 56110 all_sum = 0, 56111 even_sum = 0, 56112 odd_sum = 0, 56113 i, n, 56114 control_digit, 56115 control_letter; 56116 56117 function isOdd( n ) { 56118 return n % 2 === 0; 56119 } 56120 56121 // Quick format test 56122 if ( value.length !== 9 || !cifRegEx.test( value ) ) { 56123 return false; 56124 } 56125 56126 for ( i = 0; i < number.length; i++ ) { 56127 n = parseInt( number[ i ], 10 ); 56128 56129 // Odd positions 56130 if ( isOdd( i ) ) { 56131 56132 // Odd positions are multiplied first. 56133 n *= 2; 56134 56135 // If the multiplication is bigger than 10 we need to adjust 56136 odd_sum += n < 10 ? n : n - 9; 56137 56138 // Even positions 56139 // Just sum them 56140 } else { 56141 even_sum += n; 56142 } 56143 } 56144 56145 all_sum = even_sum + odd_sum; 56146 control_digit = ( 10 - ( all_sum ).toString().substr( -1 ) ).toString(); 56147 control_digit = parseInt( control_digit, 10 ) > 9 ? "0" : control_digit; 56148 control_letter = "JABCDEFGHI".substr( control_digit, 1 ).toString(); 56149 56150 // Control must be a digit 56151 if ( letter.match( /[ABEH]/ ) ) { 56152 return control === control_digit; 56153 56154 // Control must be a letter 56155 } else if ( letter.match( /[KPQS]/ ) ) { 56156 return control === control_letter; 56157 } 56158 56159 // Can be either 56160 return control === control_digit || control === control_letter; 56161 56162}, "Please specify a valid CIF number." ); 56163 56164/* 56165 * Brazillian CNH number (Carteira Nacional de Habilitacao) is the License Driver number. 56166 * CNH numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation. 56167 */ 56168$.validator.addMethod( "cnhBR", function( value ) { 56169 56170 // Removing special characters from value 56171 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" ); 56172 56173 // Checking value to have 11 digits only 56174 if ( value.length !== 11 ) { 56175 return false;
vendor: 28,001 bytes, lines 56176-57067
56176 } 56177 56178 var sum = 0, dsc = 0, firstChar, 56179 firstCN, secondCN, i, j, v; 56180 56181 firstChar = value.charAt( 0 ); 56182 56183 if ( new Array( 12 ).join( firstChar ) === value ) { 56184 return false; 56185 } 56186 56187 // Step 1 - using first Check Number: 56188 for ( i = 0, j = 9, v = 0; i < 9; ++i, --j ) { 56189 sum += +( value.charAt( i ) * j ); 56190 } 56191 56192 firstCN = sum % 11; 56193 if ( firstCN >= 10 ) { 56194 firstCN = 0; 56195 dsc = 2; 56196 } 56197 56198 sum = 0; 56199 for ( i = 0, j = 1, v = 0; i < 9; ++i, ++j ) { 56200 sum += +( value.charAt( i ) * j ); 56201 } 56202 56203 secondCN = sum % 11; 56204 if ( secondCN >= 10 ) { 56205 secondCN = 0; 56206 } else { 56207 secondCN = secondCN - dsc; 56208 } 56209 56210 return ( String( firstCN ).concat( secondCN ) === value.substr( -2 ) ); 56211 56212}, "Please specify a valid CNH number" ); 56213 56214/* 56215 * Brazillian value number (Cadastrado de Pessoas Juridica). 56216 * value numbers have 14 digits in total: 12 numbers followed by 2 check numbers that are being used for validation. 56217 */ 56218$.validator.addMethod( "cnpjBR", function( value, element ) { 56219 "use strict"; 56220 56221 if ( this.optional( element ) ) { 56222 return true; 56223 } 56224 56225 // Removing no number 56226 value = value.replace( /[^\d]+/g, "" ); 56227 56228 // Checking value to have 14 digits only 56229 if ( value.length !== 14 ) { 56230 return false; 56231 } 56232 56233 // Elimina values invalidos conhecidos 56234 if ( value === "00000000000000" || 56235 value === "11111111111111" || 56236 value === "22222222222222" || 56237 value === "33333333333333" || 56238 value === "44444444444444" || 56239 value === "55555555555555" || 56240 value === "66666666666666" || 56241 value === "77777777777777" || 56242 value === "88888888888888" || 56243 value === "99999999999999" ) { 56244 return false; 56245 } 56246 56247 // Valida DVs 56248 var tamanho = ( value.length - 2 ); 56249 var numeros = value.substring( 0, tamanho ); 56250 var digitos = value.substring( tamanho ); 56251 var soma = 0; 56252 var pos = tamanho - 7; 56253 56254 for ( var i = tamanho; i >= 1; i-- ) { 56255 soma += numeros.charAt( tamanho - i ) * pos--; 56256 if ( pos < 2 ) { 56257 pos = 9; 56258 } 56259 } 56260 56261 var resultado = soma % 11 < 2 ? 0 : 11 - soma % 11; 56262 56263 if ( resultado !== parseInt( digitos.charAt( 0 ), 10 ) ) { 56264 return false; 56265 } 56266 56267 tamanho = tamanho + 1; 56268 numeros = value.substring( 0, tamanho ); 56269 soma = 0; 56270 pos = tamanho - 7; 56271 56272 for ( var il = tamanho; il >= 1; il-- ) { 56273 soma += numeros.charAt( tamanho - il ) * pos--; 56274 if ( pos < 2 ) { 56275 pos = 9; 56276 } 56277 } 56278 56279 resultado = soma % 11 < 2 ? 0 : 11 - soma % 11; 56280 56281 if ( resultado !== parseInt( digitos.charAt( 1 ), 10 ) ) { 56282 return false; 56283 } 56284 56285 return true; 56286 56287}, "Please specify a CNPJ value number" ); 56288 56289/* 56290 * Brazillian CPF number (Cadastrado de Pessoas FÃsicas) is the equivalent of a Brazilian tax registration number. 56291 * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation. 56292 */ 56293$.validator.addMethod( "cpfBR", function( value, element ) { 56294 "use strict"; 56295 56296 if ( this.optional( element ) ) { 56297 return true; 56298 } 56299 56300 // Removing special characters from value 56301 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" ); 56302 56303 // Checking value to have 11 digits only 56304 if ( value.length !== 11 ) { 56305 return false; 56306 } 56307 56308 var sum = 0, 56309 firstCN, secondCN, checkResult, i; 56310 56311 firstCN = parseInt( value.substring( 9, 10 ), 10 ); 56312 secondCN = parseInt( value.substring( 10, 11 ), 10 ); 56313 56314 checkResult = function( sum, cn ) { 56315 var result = ( sum * 10 ) % 11; 56316 if ( ( result === 10 ) || ( result === 11 ) ) { 56317 result = 0; 56318 } 56319 return ( result === cn ); 56320 }; 56321 56322 // Checking for dump data 56323 if ( value === "" || 56324 value === "00000000000" || 56325 value === "11111111111" || 56326 value === "22222222222" || 56327 value === "33333333333" || 56328 value === "44444444444" || 56329 value === "55555555555" || 56330 value === "66666666666" || 56331 value === "77777777777" || 56332 value === "88888888888" || 56333 value === "99999999999" 56334 ) { 56335 return false; 56336 } 56337 56338 // Step 1 - using first Check Number: 56339 for ( i = 1; i <= 9; i++ ) { 56340 sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i ); 56341 } 56342 56343 // If first Check Number (CN) is valid, move to Step 2 - using second Check Number: 56344 if ( checkResult( sum, firstCN ) ) { 56345 sum = 0; 56346 for ( i = 1; i <= 10; i++ ) { 56347 sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i ); 56348 } 56349 return checkResult( sum, secondCN ); 56350 } 56351 return false; 56352 56353}, "Please specify a valid CPF number" ); 56354 56355// https://jqueryvalidation.org/creditcard-method/ 56356// based on https://en.wikipedia.org/wiki/Luhn_algorithm 56357$.validator.addMethod( "creditcard", function( value, element ) { 56358 if ( this.optional( element ) ) { 56359 return "dependency-mismatch"; 56360 } 56361 56362 // Accept only spaces, digits and dashes 56363 if ( /[^0-9 \-]+/.test( value ) ) { 56364 return false; 56365 } 56366 56367 var nCheck = 0, 56368 nDigit = 0, 56369 bEven = false, 56370 n, cDigit; 56371 56372 value = value.replace( /\D/g, "" ); 56373 56374 // Basing min and max length on 56375 // https://dev.ean.com/general-info/valid-card-types/ 56376 if ( value.length < 13 || value.length > 19 ) { 56377 return false; 56378 } 56379 56380 for ( n = value.length - 1; n >= 0; n-- ) { 56381 cDigit = value.charAt( n ); 56382 nDigit = parseInt( cDigit, 10 ); 56383 if ( bEven ) { 56384 if ( ( nDigit *= 2 ) > 9 ) { 56385 nDigit -= 9; 56386 } 56387 } 56388 56389 nCheck += nDigit; 56390 bEven = !bEven; 56391 } 56392 56393 return ( nCheck % 10 ) === 0; 56394}, "Please enter a valid credit card number." ); 56395 56396/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator 56397 * Redistributed under the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0 56398 * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings) 56399 */ 56400$.validator.addMethod( "creditcardtypes", function( value, element, param ) { 56401 if ( /[^0-9\-]+/.test( value ) ) { 56402 return false; 56403 } 56404 56405 value = value.replace( /\D/g, "" ); 56406 56407 var validTypes = 0x0000; 56408 56409 if ( param.mastercard ) { 56410 validTypes |= 0x0001; 56411 } 56412 if ( param.visa ) { 56413 validTypes |= 0x0002; 56414 } 56415 if ( param.amex ) { 56416 validTypes |= 0x0004; 56417 } 56418 if ( param.dinersclub ) { 56419 validTypes |= 0x0008; 56420 } 56421 if ( param.enroute ) { 56422 validTypes |= 0x0010; 56423 } 56424 if ( param.discover ) { 56425 validTypes |= 0x0020; 56426 } 56427 if ( param.jcb ) { 56428 validTypes |= 0x0040; 56429 } 56430 if ( param.unknown ) { 56431 validTypes |= 0x0080; 56432 } 56433 if ( param.all ) { 56434 validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080; 56435 } 56436 if ( validTypes & 0x0001 && ( /^(5[12345])/.test( value ) || /^(2[234567])/.test( value ) ) ) { // Mastercard 56437 return value.length === 16; 56438 } 56439 if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa 56440 return value.length === 16; 56441 } 56442 if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex 56443 return value.length === 15; 56444 } 56445 if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub 56446 return value.length === 14; 56447 } 56448 if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute 56449 return value.length === 15; 56450 } 56451 if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover 56452 return value.length === 16; 56453 } 56454 if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb 56455 return value.length === 16; 56456 } 56457 if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb 56458 return value.length === 15; 56459 } 56460 if ( validTypes & 0x0080 ) { // Unknown 56461 return true; 56462 } 56463 return false; 56464}, "Please enter a valid credit card number." ); 56465 56466/** 56467 * Validates currencies with any given symbols by @jameslouiz 56468 * Symbols can be optional or required. Symbols required by default 56469 * 56470 * Usage examples: 56471 * currency: ["£", false] - Use false for soft currency validation 56472 * currency: ["$", false] 56473 * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc 56474 * 56475 * <input class="currencyInput" name="currencyInput"> 56476 * 56477 * Soft symbol checking 56478 * currencyInput: { 56479 * currency: ["$", false] 56480 * } 56481 * 56482 * Strict symbol checking (default) 56483 * currencyInput: { 56484 * currency: "$" 56485 * //OR 56486 * currency: ["$", true] 56487 * } 56488 * 56489 * Multiple Symbols 56490 * currencyInput: { 56491 * currency: "$,£,¢" 56492 * } 56493 */ 56494$.validator.addMethod( "currency", function( value, element, param ) { 56495 var isParamString = typeof param === "string", 56496 symbol = isParamString ? param : param[ 0 ], 56497 soft = isParamString ? true : param[ 1 ], 56498 regex; 56499 56500 symbol = symbol.replace( /,/g, "" ); 56501 symbol = soft ? symbol + "]" : symbol + "]?"; 56502 regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$"; 56503 regex = new RegExp( regex ); 56504 return this.optional( element ) || regex.test( value ); 56505 56506}, "Please specify a valid currency" ); 56507 56508$.validator.addMethod( "dateFA", function( value, element ) { 56509 return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value ); 56510}, $.validator.messages.date ); 56511 56512/** 56513 * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy. 56514 * 56515 * @example $.validator.methods.date("01/01/1900") 56516 * @result true 56517 * 56518 * @example $.validator.methods.date("01/13/1990") 56519 * @result false 56520 * 56521 * @example $.validator.methods.date("01.01.1900") 56522 * @result false 56523 * 56524 * @example <input name="pippo" class="{dateITA:true}" /> 56525 * @desc Declares an optional input element whose value must be a valid date. 56526 * 56527 * @name $.validator.methods.dateITA 56528 * @type Boolean 56529 * @cat Plugins/Validate/Methods 56530 */ 56531$.validator.addMethod( "dateITA", function( value, element ) { 56532 var check = false, 56533 re = /^\d{1,2}\/\d{1,2}\/\d{4}$/, 56534 adata, gg, mm, aaaa, xdata; 56535 if ( re.test( value ) ) { 56536 adata = value.split( "/" ); 56537 gg = parseInt( adata[ 0 ], 10 ); 56538 mm = parseInt( adata[ 1 ], 10 ); 56539 aaaa = parseInt( adata[ 2 ], 10 ); 56540 xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) ); 56541 if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) { 56542 check = true; 56543 } else { 56544 check = false; 56545 } 56546 } else { 56547 check = false; 56548 } 56549 return this.optional( element ) || check; 56550}, $.validator.messages.date ); 56551 56552$.validator.addMethod( "dateNL", function( value, element ) { 56553 return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value ); 56554}, $.validator.messages.date ); 56555 56556// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept 56557$.validator.addMethod( "extension", function( value, element, param ) { 56558 param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif"; 56559 return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) ); 56560}, $.validator.format( "Please enter a value with a valid extension." ) ); 56561 56562/** 56563 * Dutch giro account numbers (not bank numbers) have max 7 digits 56564 */ 56565$.validator.addMethod( "giroaccountNL", function( value, element ) { 56566 return this.optional( element ) || /^[0-9]{1,7}$/.test( value ); 56567}, "Please specify a valid giro account number" ); 56568 56569$.validator.addMethod( "greaterThan", function( value, element, param ) { 56570 var target = $( param ); 56571 56572 if ( this.settings.onfocusout && target.not( ".validate-greaterThan-blur" ).length ) { 56573 target.addClass( "validate-greaterThan-blur" ).on( "blur.validate-greaterThan", function() { 56574 $( element ).valid(); 56575 } ); 56576 } 56577 56578 return value > target.val(); 56579}, "Please enter a greater value." ); 56580 56581$.validator.addMethod( "greaterThanEqual", function( value, element, param ) { 56582 var target = $( param ); 56583 56584 if ( this.settings.onfocusout && target.not( ".validate-greaterThanEqual-blur" ).length ) { 56585 target.addClass( "validate-greaterThanEqual-blur" ).on( "blur.validate-greaterThanEqual", function() { 56586 $( element ).valid(); 56587 } ); 56588 } 56589 56590 return value >= target.val(); 56591}, "Please enter a greater value." ); 56592 56593/** 56594 * IBAN is the international bank account number. 56595 * It has a country - specific format, that is checked here too 56596 * 56597 * Validation is case-insensitive. Please make sure to normalize input yourself. 56598 */ 56599$.validator.addMethod( "iban", function( value, element ) { 56600 56601 // Some quick simple tests to prevent needless work 56602 if ( this.optional( element ) ) { 56603 return true; 56604 } 56605 56606 // Remove spaces and to upper case 56607 var iban = value.replace( / /g, "" ).toUpperCase(), 56608 ibancheckdigits = "", 56609 leadingZeroes = true, 56610 cRest = "", 56611 cOperator = "", 56612 countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p; 56613 56614 // Check for IBAN code length. 56615 // It contains: 56616 // country code ISO 3166-1 - two letters, 56617 // two check digits, 56618 // Basic Bank Account Number (BBAN) - up to 30 chars 56619 var minimalIBANlength = 5; 56620 if ( iban.length < minimalIBANlength ) { 56621 return false; 56622 } 56623 56624 // Check the country code and find the country specific format 56625 countrycode = iban.substring( 0, 2 ); 56626 bbancountrypatterns = { 56627 "AL": "\\d{8}[\\dA-Z]{16}", 56628 "AD": "\\d{8}[\\dA-Z]{12}", 56629 "AT": "\\d{16}", 56630 "AZ": "[\\dA-Z]{4}\\d{20}", 56631 "BE": "\\d{12}", 56632 "BH": "[A-Z]{4}[\\dA-Z]{14}", 56633 "BA": "\\d{16}", 56634 "BR": "\\d{23}[A-Z][\\dA-Z]", 56635 "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}", 56636 "CR": "\\d{17}", 56637 "HR": "\\d{17}", 56638 "CY": "\\d{8}[\\dA-Z]{16}", 56639 "CZ": "\\d{20}", 56640 "DK": "\\d{14}", 56641 "DO": "[A-Z]{4}\\d{20}", 56642 "EE": "\\d{16}", 56643 "FO": "\\d{14}", 56644 "FI": "\\d{14}", 56645 "FR": "\\d{10}[\\dA-Z]{11}\\d{2}", 56646 "GE": "[\\dA-Z]{2}\\d{16}", 56647 "DE": "\\d{18}", 56648 "GI": "[A-Z]{4}[\\dA-Z]{15}", 56649 "GR": "\\d{7}[\\dA-Z]{16}", 56650 "GL": "\\d{14}", 56651 "GT": "[\\dA-Z]{4}[\\dA-Z]{20}", 56652 "HU": "\\d{24}", 56653 "IS": "\\d{22}", 56654 "IE": "[\\dA-Z]{4}\\d{14}", 56655 "IL": "\\d{19}", 56656 "IT": "[A-Z]\\d{10}[\\dA-Z]{12}", 56657 "KZ": "\\d{3}[\\dA-Z]{13}", 56658 "KW": "[A-Z]{4}[\\dA-Z]{22}", 56659 "LV": "[A-Z]{4}[\\dA-Z]{13}", 56660 "LB": "\\d{4}[\\dA-Z]{20}", 56661 "LI": "\\d{5}[\\dA-Z]{12}", 56662 "LT": "\\d{16}", 56663 "LU": "\\d{3}[\\dA-Z]{13}", 56664 "MK": "\\d{3}[\\dA-Z]{10}\\d{2}", 56665 "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}", 56666 "MR": "\\d{23}", 56667 "MU": "[A-Z]{4}\\d{19}[A-Z]{3}", 56668 "MC": "\\d{10}[\\dA-Z]{11}\\d{2}", 56669 "MD": "[\\dA-Z]{2}\\d{18}", 56670 "ME": "\\d{18}", 56671 "NL": "[A-Z]{4}\\d{10}", 56672 "NO": "\\d{11}", 56673 "PK": "[\\dA-Z]{4}\\d{16}", 56674 "PS": "[\\dA-Z]{4}\\d{21}", 56675 "PL": "\\d{24}", 56676 "PT": "\\d{21}", 56677 "RO": "[A-Z]{4}[\\dA-Z]{16}", 56678 "SM": "[A-Z]\\d{10}[\\dA-Z]{12}", 56679 "SA": "\\d{2}[\\dA-Z]{18}", 56680 "RS": "\\d{18}", 56681 "SK": "\\d{20}", 56682 "SI": "\\d{15}", 56683 "ES": "\\d{20}", 56684 "SE": "\\d{20}", 56685 "CH": "\\d{5}[\\dA-Z]{12}", 56686 "TN": "\\d{20}", 56687 "TR": "\\d{5}[\\dA-Z]{17}", 56688 "AE": "\\d{3}\\d{16}", 56689 "GB": "[A-Z]{4}\\d{14}", 56690 "VG": "[\\dA-Z]{4}\\d{16}" 56691 }; 56692 56693 bbanpattern = bbancountrypatterns[ countrycode ]; 56694 56695 // As new countries will start using IBAN in the 56696 // future, we only check if the countrycode is known. 56697 // This prevents false negatives, while almost all 56698 // false positives introduced by this, will be caught 56699 // by the checksum validation below anyway. 56700 // Strict checking should return FALSE for unknown 56701 // countries. 56702 if ( typeof bbanpattern !== "undefined" ) { 56703 ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" ); 56704 if ( !( ibanregexp.test( iban ) ) ) { 56705 return false; // Invalid country specific format 56706 } 56707 } 56708 56709 // Now check the checksum, first convert to digits 56710 ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 ); 56711 for ( i = 0; i < ibancheck.length; i++ ) { 56712 charAt = ibancheck.charAt( i ); 56713 if ( charAt !== "0" ) { 56714 leadingZeroes = false; 56715 } 56716 if ( !leadingZeroes ) { 56717 ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt ); 56718 } 56719 } 56720 56721 // Calculate the result of: ibancheckdigits % 97 56722 for ( p = 0; p < ibancheckdigits.length; p++ ) { 56723 cChar = ibancheckdigits.charAt( p ); 56724 cOperator = "" + cRest + "" + cChar; 56725 cRest = cOperator % 97; 56726 } 56727 return cRest === 1; 56728}, "Please specify a valid IBAN" ); 56729 56730$.validator.addMethod( "integer", function( value, element ) { 56731 return this.optional( element ) || /^-?\d+$/.test( value ); 56732}, "A positive or negative non-decimal number please" ); 56733 56734$.validator.addMethod( "ipv4", function( value, element ) { 56735 return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value ); 56736}, "Please enter a valid IP v4 address." ); 56737 56738$.validator.addMethod( "ipv6", function( value, element ) { 56739 return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value ); 56740}, "Please enter a valid IP v6 address." ); 56741 56742$.validator.addMethod( "lessThan", function( value, element, param ) { 56743 var target = $( param ); 56744 56745 if ( this.settings.onfocusout && target.not( ".validate-lessThan-blur" ).length ) { 56746 target.addClass( "validate-lessThan-blur" ).on( "blur.validate-lessThan", function() { 56747 $( element ).valid(); 56748 } ); 56749 } 56750 56751 return value < target.val(); 56752}, "Please enter a lesser value." ); 56753 56754$.validator.addMethod( "lessThanEqual", function( value, element, param ) { 56755 var target = $( param ); 56756 56757 if ( this.settings.onfocusout && target.not( ".validate-lessThanEqual-blur" ).length ) { 56758 target.addClass( "validate-lessThanEqual-blur" ).on( "blur.validate-lessThanEqual", function() { 56759 $( element ).valid(); 56760 } ); 56761 } 56762 56763 return value <= target.val(); 56764}, "Please enter a lesser value." ); 56765 56766$.validator.addMethod( "lettersonly", function( value, element ) { 56767 return this.optional( element ) || /^[a-z]+$/i.test( value ); 56768}, "Letters only please" ); 56769 56770$.validator.addMethod( "letterswithbasicpunc", function( value, element ) { 56771 return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value ); 56772}, "Letters or punctuation only please" ); 56773 56774// Limit the number of files in a FileList. 56775$.validator.addMethod( "maxfiles", function( value, element, param ) { 56776 if ( this.optional( element ) ) { 56777 return true; 56778 } 56779 56780 if ( $( element ).attr( "type" ) === "file" ) { 56781 if ( element.files && element.files.length > param ) { 56782 return false; 56783 } 56784 } 56785 56786 return true; 56787}, $.validator.format( "Please select no more than {0} files." ) ); 56788 56789// Limit the size of each individual file in a FileList. 56790$.validator.addMethod( "maxsize", function( value, element, param ) { 56791 if ( this.optional( element ) ) { 56792 return true; 56793 } 56794 56795 if ( $( element ).attr( "type" ) === "file" ) { 56796 if ( element.files && element.files.length ) { 56797 for ( var i = 0; i < element.files.length; i++ ) { 56798 if ( element.files[ i ].size > param ) { 56799 return false; 56800 } 56801 } 56802 } 56803 } 56804 56805 return true; 56806}, $.validator.format( "File size must not exceed {0} bytes each." ) ); 56807 56808// Limit the size of all files in a FileList. 56809$.validator.addMethod( "maxsizetotal", function( value, element, param ) { 56810 if ( this.optional( element ) ) { 56811 return true; 56812 } 56813 56814 if ( $( element ).attr( "type" ) === "file" ) { 56815 if ( element.files && element.files.length ) { 56816 var totalSize = 0; 56817 56818 for ( var i = 0; i < element.files.length; i++ ) { 56819 totalSize += element.files[ i ].size; 56820 if ( totalSize > param ) { 56821 return false; 56822 } 56823 } 56824 } 56825 } 56826 56827 return true; 56828}, $.validator.format( "Total size of all files must not exceed {0} bytes." ) ); 56829 56830 56831$.validator.addMethod( "mobileNL", function( value, element ) { 56832 return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value ); 56833}, "Please specify a valid mobile number" ); 56834 56835$.validator.addMethod( "mobileRU", function( phone_number, element ) { 56836 var ruPhone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); 56837 return this.optional( element ) || ruPhone_number.length > 9 && /^((\+7|7|8)+([0-9]){10})$/.test( ruPhone_number ); 56838}, "Please specify a valid mobile number" ); 56839 56840/* For UK phone functions, do the following server side processing: 56841 * Compare original input with this RegEx pattern: 56842 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ 56843 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0' 56844 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. 56845 * A number of very detailed GB telephone number RegEx patterns can also be found at: 56846 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers 56847 */ 56848$.validator.addMethod( "mobileUK", function( phone_number, element ) { 56849 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); 56850 return this.optional( element ) || phone_number.length > 9 && 56851 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ ); 56852}, "Please specify a valid mobile number" ); 56853 56854$.validator.addMethod( "netmask", function( value, element ) { 56855 return this.optional( element ) || /^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test( value ); 56856}, "Please enter a valid netmask." ); 56857 56858/* 56859 * The NIE (Número de Identificación de Extranjero) is a Spanish tax identification number assigned by the Spanish 56860 * authorities to any foreigner. 56861 * 56862 * The NIE is the equivalent of a Spaniards Número de Identificación Fiscal (NIF) which serves as a fiscal 56863 * identification number. The CIF number (Certificado de Identificación Fiscal) is equivalent to the NIF, but applies to 56864 * companies rather than individuals. The NIE consists of an 'X' or 'Y' followed by 7 or 8 digits then another letter. 56865 */ 56866$.validator.addMethod( "nieES", function( value, element ) { 56867 "use strict"; 56868 56869 if ( this.optional( element ) ) { 56870 return true; 56871 } 56872 56873 var nieRegEx = new RegExp( /^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi ); 56874 var validChars = "TRWAGMYFPDXBNJZSQVHLCKET", 56875 letter = value.substr( value.length - 1 ).toUpperCase(), 56876 number; 56877 56878 value = value.toString().toUpperCase(); 56879 56880 // Quick format test 56881 if ( value.length > 10 || value.length < 9 || !nieRegEx.test( value ) ) { 56882 return false; 56883 } 56884 56885 // X means same number 56886 // Y means number + 10000000 56887 // Z means number + 20000000 56888 value = value.replace( /^[X]/, "0" ) 56889 .replace( /^[Y]/, "1" ) 56890 .replace( /^[Z]/, "2" ); 56891 56892 number = value.length === 9 ? value.substr( 0, 8 ) : value.substr( 0, 9 ); 56893 56894 return validChars.charAt( parseInt( number, 10 ) % 23 ) === letter; 56895 56896}, "Please specify a valid NIE number." ); 56897 56898/* 56899 * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals 56900 */ 56901$.validator.addMethod( "nifES", function( value, element ) { 56902 "use strict"; 56903 56904 if ( this.optional( element ) ) { 56905 return true; 56906 } 56907 56908 value = value.toUpperCase(); 56909 56910 // Basic format test 56911 if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) { 56912 return false; 56913 } 56914 56915 // Test NIF 56916 if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) { 56917 return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) ); 56918 } 56919 56920 // Test specials NIF (starts with K, L or M) 56921 if ( /^[KLM]{1}/.test( value ) ) { 56922 return ( value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 1 ) % 23 ) ); 56923 } 56924 56925 return false; 56926 56927}, "Please specify a valid NIF number." ); 56928 56929/* 56930 * Numer identyfikacji podatkowej ( NIP ) is the way tax identification used in Poland for companies 56931 */ 56932$.validator.addMethod( "nipPL", function( value ) { 56933 "use strict"; 56934 56935 value = value.replace( /[^0-9]/g, "" ); 56936 56937 if ( value.length !== 10 ) { 56938 return false; 56939 } 56940 56941 var arrSteps = [ 6, 5, 7, 2, 3, 4, 5, 6, 7 ]; 56942 var intSum = 0; 56943 for ( var i = 0; i < 9; i++ ) { 56944 intSum += arrSteps[ i ] * value[ i ]; 56945 } 56946 var int2 = intSum % 11; 56947 var intControlNr = ( int2 === 10 ) ? 0 : int2; 56948 56949 return ( intControlNr === parseInt( value[ 9 ], 10 ) ); 56950}, "Please specify a valid NIP number." ); 56951 56952/** 56953 * Created for project jquery-validation. 56954 * @Description Brazillian PIS or NIS number (Número de Identificação Social Pis ou Pasep) is the equivalent of a 56955 * Brazilian tax registration number NIS of PIS numbers have 11 digits in total: 10 numbers followed by 1 check numbers 56956 * that are being used for validation. 56957 * @copyright (c) 21/08/2018 13:14, Cleiton da Silva Mendonça 56958 * @author Cleiton da Silva Mendonça <[email protected]> 56959 * @link http://gitlab.com/csmendonca Gitlab of Cleiton da Silva Mendonça 56960 * @link http://github.com/csmendonca Github of Cleiton da Silva Mendonça 56961 */ 56962$.validator.addMethod( "nisBR", function( value ) { 56963 var number; 56964 var cn; 56965 var sum = 0; 56966 var dv; 56967 var count; 56968 var multiplier; 56969 56970 // Removing special characters from value 56971 value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" ); 56972 56973 // Checking value to have 11 digits only 56974 if ( value.length !== 11 ) { 56975 return false; 56976 } 56977 56978 //Get check number of value 56979 cn = parseInt( value.substring( 10, 11 ), 10 ); 56980 56981 //Get number with 10 digits of the value 56982 number = parseInt( value.substring( 0, 10 ), 10 ); 56983 56984 for ( count = 2; count < 12; count++ ) { 56985 multiplier = count; 56986 if ( count === 10 ) { 56987 multiplier = 2; 56988 } 56989 if ( count === 11 ) { 56990 multiplier = 3; 56991 } 56992 sum += ( ( number % 10 ) * multiplier ); 56993 number = parseInt( number / 10, 10 ); 56994 } 56995 dv = ( sum % 11 ); 56996 56997 if ( dv > 1 ) { 56998 dv = ( 11 - dv ); 56999 } else { 57000 dv = 0; 57001 } 57002 57003 if ( cn === dv ) { 57004 return true; 57005 } else { 57006 return false; 57007 } 57008}, "Please specify a valid NIS/PIS number" ); 57009 57010$.validator.addMethod( "notEqualTo", function( value, element, param ) { 57011 return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param ); 57012}, "Please enter a different value, values must not be the same." ); 57013 57014$.validator.addMethod( "nowhitespace", function( value, element ) { 57015 return this.optional( element ) || /^\S+$/i.test( value ); 57016}, "No white space please" ); 57017 57018/** 57019* Return true if the field value matches the given format RegExp 57020* 57021* @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/) 57022* @result true 57023* 57024* @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/) 57025* @result false 57026* 57027* @name $.validator.methods.pattern 57028* @type Boolean 57029* @cat Plugins/Validate/Methods 57030*/ 57031$.validator.addMethod( "pattern", function( value, element, param ) { 57032 if ( this.optional( element ) ) { 57033 return true; 57034 } 57035 if ( typeof param === "string" ) { 57036 param = new RegExp( "^(?:" + param + ")$" ); 57037 } 57038 return param.test( value ); 57039}, "Invalid format." ); 57040 57041/** 57042 * Dutch phone numbers have 10 digits (or 11 and start with +31). 57043 */ 57044$.validator.addMethod( "phoneNL", function( value, element ) { 57045 return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value ); 57046}, "Please specify a valid phone number." ); 57047 57048/** 57049 * Polish telephone numbers have 9 digits. 57050 * 57051 * Mobile phone numbers starts with following digits: 57052 * 45, 50, 51, 53, 57, 60, 66, 69, 72, 73, 78, 79, 88. 57053 * 57054 * Fixed-line numbers starts with area codes: 57055 * 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, 29, 32, 33, 57056 * 34, 41, 42, 43, 44, 46, 48, 52, 54, 55, 56, 58, 59, 61, 57057 * 62, 63, 65, 67, 68, 71, 74, 75, 76, 77, 81, 82, 83, 84, 57058 * 85, 86, 87, 89, 91, 94, 95. 57059 * 57060 * Ministry of National Defence numbers and VoIP numbers starts with 26 and 39. 57061 * 57062 * Excludes intelligent networks (premium rate, shared cost, free phone numbers). 57063 * 57064 * Poland National Numbering Plan http://www.itu.int/oth/T02020000A8/en 57065 */ 57066$.validator.addMethod( "phonePL", function( phone_number, element ) { 57067 phone_number = phone_number.replace( /\s+/g, "" );
57068 var regexp = /^(?:(?:(?:\+|00)?48)|(?:\(\+?48\)))?(?:1[2-8]|2[2-69]|3[2-49]|4[1-68]|5[0-9]|6[0-35-9]|[7-8][1-9]|9[145])\d{7}$/; 57069 return this.optional( element ) || regexp.test( phone_number ); 57070}, "Please specify a valid phone number" ); 57071 57072/* For UK phone functions, do the following server side processing: 57073 * Compare original input with this RegEx pattern: 57074 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ 57075 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0' 57076 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. 57077 * A number of very detailed GB telephone number RegEx patterns can also be found at: 57078 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers 57079 */ 57080 57081// Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers 57082$.validator.addMethod( "phonesUK", function( phone_number, element ) { 57083 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); 57084 return this.optional( element ) || phone_number.length > 9 && 57085 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ ); 57086}, "Please specify a valid uk phone number" ); 57087 57088/* For UK phone functions, do the following server side processing: 57089 * Compare original input with this RegEx pattern: 57090 * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$ 57091 * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0' 57092 * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2. 57093 * A number of very detailed GB telephone number RegEx patterns can also be found at: 57094 * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers 57095 */ 57096$.validator.addMethod( "phoneUK", function( phone_number, element ) { 57097 phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" ); 57098 return this.optional( element ) || phone_number.length > 9 && 57099 phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ ); 57100}, "Please specify a valid phone number" ); 57101 57102/** 57103 * Matches US phone number format 57104 * 57105 * where the area code may not start with 1 and the prefix may not start with 1 57106 * allows '-' or ' ' as a separator and allows parens around area code 57107 * some people may want to put a '1' in front of their number 57108 * 57109 * 1(212)-999-2345 or 57110 * 212 999 2344 or 57111 * 212-999-0983 57112 * 57113 * but not 57114 * 111-123-5434 57115 * and not 57116 * 212 123 4567 57117 */ 57118$.validator.addMethod( "phoneUS", function( phone_number, element ) { 57119 phone_number = phone_number.replace( /\s+/g, "" ); 57120 return this.optional( element ) || phone_number.length > 9 && 57121 phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]\d{2}-?\d{4}$/ ); 57122}, "Please specify a valid phone number" ); 57123 57124/* 57125* Valida CEPs do brasileiros: 57126* 57127* Formatos aceitos: 57128* 99999-999 57129* 99.999-999 57130* 99999999 57131*/ 57132$.validator.addMethod( "postalcodeBR", function( cep_value, element ) { 57133 return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value ); 57134}, "Informe um CEP válido." ); 57135 57136/** 57137 * Matches a valid Canadian Postal Code 57138 * 57139 * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element ) 57140 * @result true 57141 * 57142 * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element ) 57143 * @result false 57144 * 57145 * @name jQuery.validator.methods.postalCodeCA 57146 * @type Boolean 57147 * @cat Plugins/Validate/Methods 57148 */ 57149$.validator.addMethod( "postalCodeCA", function( value, element ) { 57150 return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value ); 57151}, "Please specify a valid postal code" ); 57152 57153/* Matches Italian postcode (CAP) */ 57154$.validator.addMethod( "postalcodeIT", function( value, element ) { 57155 return this.optional( element ) || /^\d{5}$/.test( value ); 57156}, "Please specify a valid postal code" ); 57157 57158$.validator.addMethod( "postalcodeNL", function( value, element ) { 57159 return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value ); 57160}, "Please specify a valid postal code" ); 57161 57162// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK) 57163$.validator.addMethod( "postcodeUK", function( value, element ) { 57164 return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value ); 57165}, "Please specify a valid UK postcode
vendor: 5,517 bytes, lines 57165-57302
57165" ); 57166 57167/* 57168 * Lets you say "at least X inputs that match selector Y must be filled." 57169 * 57170 * The end result is that neither of these inputs: 57171 * 57172 * <input class="productinfo" name="partnumber"> 57173 * <input class="productinfo" name="description"> 57174 * 57175 * ...will validate unless at least one of them is filled. 57176 * 57177 * partnumber: {require_from_group: [1,".productinfo"]}, 57178 * description: {require_from_group: [1,".productinfo"]} 57179 * 57180 * options[0]: number of fields that must be filled in the group 57181 * options[1]: CSS selector that defines the group of conditionally required fields 57182 */ 57183$.validator.addMethod( "require_from_group", function( value, element, options ) { 57184 var $fields = $( options[ 1 ], element.form ), 57185 $fieldsFirst = $fields.eq( 0 ), 57186 validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ), 57187 isValid = $fields.filter( function() { 57188 return validator.elementValue( this ); 57189 } ).length >= options[ 0 ]; 57190 57191 // Store the cloned validator for future validation 57192 $fieldsFirst.data( "valid_req_grp", validator ); 57193 57194 // If element isn't being validated, run each require_from_group field's validation rules 57195 if ( !$( element ).data( "being_validated" ) ) { 57196 $fields.data( "being_validated", true ); 57197 $fields.each( function() { 57198 validator.element( this ); 57199 } ); 57200 $fields.data( "being_validated", false ); 57201 } 57202 return isValid; 57203}, $.validator.format( "Please fill at least {0} of these fields." ) ); 57204 57205/* 57206 * Lets you say "either at least X inputs that match selector Y must be filled, 57207 * OR they must all be skipped (left blank)." 57208 * 57209 * The end result, is that none of these inputs: 57210 * 57211 * <input class="productinfo" name="partnumber"> 57212 * <input class="productinfo" name="description"> 57213 * <input class="productinfo" name="color"> 57214 * 57215 * ...will validate unless either at least two of them are filled, 57216 * OR none of them are. 57217 * 57218 * partnumber: {skip_or_fill_minimum: [2,".productinfo"]}, 57219 * description: {skip_or_fill_minimum: [2,".productinfo"]}, 57220 * color: {skip_or_fill_minimum: [2,".productinfo"]} 57221 * 57222 * options[0]: number of fields that must be filled in the group 57223 * options[1]: CSS selector that defines the group of conditionally required fields 57224 * 57225 */ 57226$.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) { 57227 var $fields = $( options[ 1 ], element.form ), 57228 $fieldsFirst = $fields.eq( 0 ), 57229 validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ), 57230 numberFilled = $fields.filter( function() { 57231 return validator.elementValue( this ); 57232 } ).length, 57233 isValid = numberFilled === 0 || numberFilled >= options[ 0 ]; 57234 57235 // Store the cloned validator for future validation 57236 $fieldsFirst.data( "valid_skip", validator ); 57237 57238 // If element isn't being validated, run each skip_or_fill_minimum field's validation rules 57239 if ( !$( element ).data( "being_validated" ) ) { 57240 $fields.data( "being_validated", true ); 57241 $fields.each( function() { 57242 validator.element( this ); 57243 } ); 57244 $fields.data( "being_validated", false ); 57245 } 57246 return isValid; 57247}, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) ); 57248 57249/* Validates US States and/or Territories by @jdforsythe 57250 * Can be case insensitive or require capitalization - default is case insensitive 57251 * Can include US Territories or not - default does not 57252 * Can include US Military postal abbreviations (AA, AE, AP) - default does not 57253 * 57254 * Note: "States" always includes DC (District of Colombia) 57255 * 57256 * Usage examples: 57257 * 57258 * This is the default - case insensitive, no territories, no military zones 57259 * stateInput: { 57260 * caseSensitive: false, 57261 * includeTerritories: false, 57262 * includeMilitary: false 57263 * } 57264 * 57265 * Only allow capital letters, no territories, no military zones 57266 * stateInput: { 57267 * caseSensitive: false 57268 * } 57269 * 57270 * Case insensitive, include territories but not military zones 57271 * stateInput: { 57272 * includeTerritories: true 57273 * } 57274 * 57275 * Only allow capital letters, include territories and military zones 57276 * stateInput: { 57277 * caseSensitive: true, 57278 * includeTerritories: true, 57279 * includeMilitary: true 57280 * } 57281 * 57282 */ 57283$.validator.addMethod( "stateUS", function( value, element, options ) { 57284 var isDefault = typeof options === "undefined", 57285 caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive, 57286 includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories, 57287 includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary, 57288 regex; 57289 57290 if ( !includeTerritories && !includeMilitary ) { 57291 regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$"; 57292 } else if ( includeTerritories && includeMilitary ) { 57293 regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$"; 57294 } else if ( includeTerritories ) { 57295 regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$"; 57296 } else { 57297 regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$"; 57298 } 57299 57300 regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" ); 57301 return this.optional( element ) || regex.test( value ); 57302}, "Please specify a valid state
vendor: 2,891 bytes, lines 57302-57343
57302" ); 57303 57304// TODO check if value starts with <, otherwise don't try stripping anything 57305$.validator.addMethod( "strippedminlength", function( value, element, param ) { 57306 return $( value ).text().length >= param; 57307}, $.validator.format( "Please enter at least {0} characters" ) ); 57308 57309$.validator.addMethod( "time", function( value, element ) { 57310 return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value ); 57311}, "Please enter a valid time, between 00:00 and 23:59" ); 57312 57313$.validator.addMethod( "time12h", function( value, element ) { 57314 return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value ); 57315}, "Please enter a valid time in 12-hour am/pm format" ); 57316 57317// Same as url, but TLD is optional 57318$.validator.addMethod( "url2", function( value, element ) { 57319 return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value ); 57320}, $.validator.messages.url ); 57321 57322/** 57323 * Return true, if the value is a valid vehicle identification number (VIN). 57324 * 57325 * Works with all kind of text inputs. 57326 * 57327 * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" /> 57328 * @desc Declares a required input element whose value must be a valid vehicle identification number. 57329 * 57330 * @name $.validator.methods.vinUS 57331 * @type Boolean 57332 * @cat Plugins/Validate/Methods 57333 */ 57334$.validator.addMethod( "vinUS", function( v ) { 57335 if ( v.length !== 17 ) { 57336 return false; 57337 } 57338 57339 var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ], 57340 VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ], 57341 FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ], 57342 rs = 0, 57343 i, n, d, f, cd, cdv;
57344 57345 for ( i = 0; i < 17; i++ ) { 57346 f = FL[ i ]; 57347 d = v.slice( i, i + 1 ); 57348 if ( i === 8 ) { 57349 cdv = d; 57350 } 57351 if ( !isNaN( d ) ) { 57352 d *= f; 57353 } else { 57354 for ( n = 0; n < LL.length; n++ ) { 57355 if ( d.toUpperCase() === LL[ n ] ) { 57356 d = VL[ n ]; 57357 d *= f; 57358 if ( isNaN( cdv ) && n === 8 ) { 57359 cdv = LL[ n ]; 57360 } 57361 break; 57362 } 57363 } 57364 } 57365 rs += d; 57366 } 57367 cd = rs % 11; 57368 if ( cd === 10 ) { 57369 cd = "X"; 57370 } 57371 if ( cd === cdv ) { 57372 return true; 57373 } 57374 return false; 57375}, "The specified vehicle identification number (VIN) is invalid." ); 57376 57377$.validator.addMethod( "zipcodeUS", function( value, element ) { 57378 return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value ); 57379}, "The specified US ZIP Code is invalid" ); 57380 57381$.validator.addMethod( "ziprange", function( value, element ) { 57382 return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value ); 57383}, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" ); 57384return $; 57385})); 57386"use strict"; 57387var valGetParentContainer = function(element) { 57388 var element = $(element); 57389 57390 if ($(element).closest('.form-group-sub').length > 0) { 57391 return $(element).closest('.form-group-sub') 57392 } else if ($(element).closest('.bootstrap-select').length > 0) { 57393 return $(element).closest('.bootstrap-select') 57394 } else { 57395 return $(element).closest('.form-group'); 57396 } 57397} 57398 57399jQuery.validator.setDefaults({ 57400 errorElement: 'div', //default input error message container 57401 focusInvalid: false, // do not focus the last invalid input 57402 ignore: "", // validate all fields including form hidden input 57403 57404 errorPlacement: function(error, element) { // render error placement for each input type 57405 var element = $(element); 57406 57407 var group = valGetParentContainer(element); 57408 var help = group.find('.form-text'); 57409 57410 if (group.find('.valid-feedback, .invalid-feedback').length !== 0) { 57411 return; 57412 } 57413 57414 element.addClass('is-invalid'); 57415 error.addClass('invalid-feedback'); 57416 57417 if (help.length > 0) { 57418 help.before(error); 57419 } else { 57420 if (element.closest('.bootstrap-select').length > 0) { //Bootstrap select 57421 element.closest('.bootstrap-select').find('.bs-placeholder').after(error); 57422 } else if (element.closest('.input-group').length > 0) { //Bootstrap group 57423 element.after(error); 57424 } else { //Checkbox & radios 57425 if (element.is(':checkbox')) { 57426 element.closest('.kt-checkbox').find('> span').after(error); 57427 } else { 57428 element.after(error); 57429 } 57430 } 57431 } 57432 }, 57433 57434 highlight: function(element) { // hightlight error inputs 57435 var group = valGetParentContainer(element); 57436 group.addClass('validate'); 57437 group.addClass('is-invalid'); 57438 $(element).removeClass('is-valid'); 57439 }, 57440 57441 unhighlight: function(element) { // revert the change done by hightlight 57442 var group = valGetParentContainer(element); 57443 group.removeClass('validate'); 57444 group.removeClass('is-invalid'); 57445 $(element).removeClass('is-invalid'); 57446 }, 57447 57448 success: function(label, element) { 57449 var group = valGetParentContainer(element); 57450 group.removeClass('validate'); 57451 group.find('.invalid-feedback').remove(); 57452 } 57453}); 57454 57455jQuery.validator.addMethod("email", function(value, element) { 57456 if (/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(value)) { 57457 return true; 57458 } else { 57459 return false; 57460 } 57461}, "Please enter a valid Email."); 57462!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;
vendor: 7,322 bytes, lines 57462-57505
57462o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'<button type="button">×</button>',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("<div/>"),M=e("<div/>"),B=e("<div/>"),q=e("<div/>"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.4",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)}); 57463//# sourceMappingURL=toastr.js.map 57464 57465// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ \\ 57466// â Raphaël 2.2.8 - JavaScript Vector Library â \\ 57467// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⤠\\ 57468// â Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com) â \\ 57469// â Copyright © 2008-2016 Sencha Labs (http://sencha.com) â \\ 57470// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⤠\\ 57471// â Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.â \\ 57472// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ \\ 57473 57474(function webpackUniversalModuleDefinition(root, factory) { 57475 if(typeof exports === 'object' && typeof module === 'object') 57476 module.exports = factory(); 57477 else if(typeof define === 'function' && define.amd) 57478 define([], factory); 57479 else if(typeof exports === 'object') 57480 exports["Raphael"] = factory(); 57481 else 57482 root["Raphael"] = factory(); 57483})(window, function() { 57484return /******/ (function(modules) { // webpackBootstrap 57485/******/ // The module cache 57486/******/ var installedModules = {}; 57487/******/ 57488/******/ // The require function 57489/******/ function __webpack_require__(moduleId) { 57490/******/ 57491/******/ // Check if module is in cache 57492/******/ if(installedModules[moduleId]) { 57493/******/ return installedModules[moduleId].exports; 57494/******/ } 57495/******/ // Create a new module (and put it into the cache) 57496/******/ var module = installedModules[moduleId] = { 57497/******/ i: moduleId, 57498/******/ l: false, 57499/******/ exports: {} 57500/******/ }; 57501/******/ 57502/******/ // Execute the module function 57503/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 57504/******/ 57505/******/ // Flag the module as loaded
vendor: 2,843 bytes, lines 57506-57571
57506/******/ module.l = true; 57507/******/ 57508/******/ // Return the exports of the module 57509/******/ return module.exports; 57510/******/ } 57511/******/ 57512/******/ 57513/******/ // expose the modules object (__webpack_modules__) 57514/******/ __webpack_require__.m = modules; 57515/******/ 57516/******/ // expose the module cache 57517/******/ __webpack_require__.c = installedModules; 57518/******/ 57519/******/ // define getter function for harmony exports 57520/******/ __webpack_require__.d = function(exports, name, getter) { 57521/******/ if(!__webpack_require__.o(exports, name)) { 57522/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 57523/******/ } 57524/******/ }; 57525/******/ 57526/******/ // define __esModule on exports 57527/******/ __webpack_require__.r = function(exports) { 57528/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 57529/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 57530/******/ } 57531/******/ Object.defineProperty(exports, '__esModule', { value: true }); 57532/******/ }; 57533/******/ 57534/******/ // create a fake namespace object 57535/******/ // mode & 1: value is a module id, require it 57536/******/ // mode & 2: merge all properties of value into the ns 57537/******/ // mode & 4: return value when already ns object 57538/******/ // mode & 8|1: behave like require 57539/******/ __webpack_require__.t = function(value, mode) { 57540/******/ if(mode & 1) value = __webpack_require__(value); 57541/******/ if(mode & 8) return value; 57542/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 57543/******/ var ns = Object.create(null); 57544/******/ __webpack_require__.r(ns); 57545/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 57546/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 57547/******/ return ns; 57548/******/ }; 57549/******/ 57550/******/ // getDefaultExport function for compatibility with non-harmony modules 57551/******/ __webpack_require__.n = function(module) { 57552/******/ var getter = module && module.__esModule ? 57553/******/ function getDefault() { return module['default']; } : 57554/******/ function getModuleExports() { return module; }; 57555/******/ __webpack_require__.d(getter, 'a', getter); 57556/******/ return getter; 57557/******/ }; 57558/******/ 57559/******/ // Object.prototype.hasOwnProperty.call 57560/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 57561/******/ 57562/******/ // __webpack_public_path__ 57563/******/ __webpack_require__.p = ""; 57564/******/ 57565/******/ 57566/******/ // Load entry module and return exports 57567/******/ return __webpack_require__(__webpack_require__.s = "./dev/raphael.amd.js"); 57568/******/ }) 57569/************************************************************************/ 57570/******/ ({ 57571
57572/***/ "./dev/raphael.amd.js": 57573/*!****************************!*\ 57574 !*** ./dev/raphael.amd.js ***! 57575 \****************************/ 57576/*! no static exports found */ 57577/***/ (function(module, exports, __webpack_require__) { 57578 57579eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\"), __webpack_require__(/*! ./raphael.svg */ \"./dev/raphael.svg.js\"), __webpack_require__(/*! ./raphael.vml */ \"./dev/raphael.vml.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n\n return R;\n\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5hbWQuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwuYW1kLmpzPzM1NjQiXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCIsIFwiLi9yYXBoYWVsLnN2Z1wiLCBcIi4vcmFwaGFlbC52bWxcIl0sIGZ1bmN0aW9uKFIpIHtcblxuICAgIHJldHVybiBSO1xuXG59KTsiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./dev/raphael.amd.js\n"); 57580 57581/***/ }), 57582
57583/***/ "./dev/raphael.core.js": 57584/*!*****************************!*\ 57585 !*** ./dev/raphael.core.js ***! 57586 \*****************************/ 57587/*! no static exports found */ 57588/***/ (function(module, exports, __webpack_require__) { 57589 57590eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! eve */ \"./node_modules/eve-raphael/eve.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(eve) {\n\n /*\\\n * Raphael\n [ method ]\n **\n * Creates a canvas object on which to draw.\n * You must do this first, as all future calls to drawing methods\n * from this instance will be bound to this canvas.\n > Parameters\n **\n - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface\n - width (number)\n - height (number)\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - x (number)\n - y (number)\n - width (number)\n - height (number)\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add.\n - callback (function) #optional callback function which is going to be executed in the context of newly created paper\n * or\n - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eveâs âDOMLoadâ event. In this case method returns `undefined`.\n = (object) @Paper\n > Usage\n | // Each of the following examples create a canvas\n | // that is 320px wide by 200px high.\n | // Canvas is created at the viewportâs 10,50 coordinate.\n | var paper = Raphael(10, 50, 320, 200);\n | // Canvas is created at the top left corner of the #notepad element\n | // (or its top right corner in dir=\"rtl\" elements)\n | var paper = Raphael(document.getElementById(\"notepad\"), 320, 200);\n | // Same as above\n | var paper = Raphael(\"notepad\", 320, 200);\n | // Image dump\n | var set = Raphael([\"notepad\", 320, 200, {\n | type: \"rect\",\n | x: 10,\n | y: 10,\n | width: 25,\n | height: 25,\n | stroke: \"#f00\"\n | }, {\n | type: \"text\",\n | x: 30,\n | y: 40,\n | text: \"Dump\"\n | }]);\n \\*/\n function R(first) {\n if (R.is(first, \"function\")) {\n return loaded ? first() : eve.on(\"raphael.DOMload\", first);\n } else if (R.is(first, array)) {\n return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);\n } else {\n var args = Array.prototype.slice.call(arguments, 0);\n if (R.is(args[args.length - 1], \"function\")) {\n var f = args.pop();\n return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on(\"raphael.DOMload\", function () {\n f.call(R._engine.create[apply](R, args));\n });\n } else {\n return R._engine.create[apply](R, arguments);\n }\n }\n }\n R.version = \"2.2.0\";\n R.eve = eve;\n var loaded,\n separator = /[, ]+/,\n elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},\n formatrg = /\\{(\\d+)\\}/g,\n proto = \"prototype\",\n has = \"hasOwnProperty\",\n g = {\n doc: document,\n win: window\n },\n oldRaphael = {\n was: Object.prototype[has].call(g.win, \"Raphael\"),\n is: g.win.Raphael\n },\n Paper = function () {\n /*\\\n * Paper.ca\n [ property (object) ]\n **\n * Shortcut for @Paper.customAttributes\n \\*/\n /*\\\n * Paper.customAttributes\n [ property (object) ]\n **\n * If you have a set of attributes that you would like to represent\n * as a function of some number you can do it easily with custom attributes:\n > Usage\n | paper.customAttributes.hue = function (num) {\n | num = num % 1;\n | return {fill: \"hsb(\" + num + \", 0.75, 1)\"};\n | };\n | // Custom attribute âhueâ will change fill\n | // to be given hue with fixed saturation and brightness.\n | // Now you can use it like this:\n | var c = paper.circle(10, 10, 10).attr({hue: .45});\n | // or even like this:\n | c.animate({hue: 1}, 1e3);\n |\n | // You could also create custom attribute\n | // with multiple parameters:\n | paper.customAttributes.hsb = function (h, s, b) {\n | return {fill: \"hsb(\" + [h, s, b].join(\",\") + \")\"};\n | };\n | c.attr({hsb: \"0.5 .8 1\"});\n | c.animate({hsb: [1, 0, 0.5]}, 1e3);\n \\*/\n this.ca = this.customAttributes = {};\n },\n paperproto,\n appendChild = \"appendChild\",\n apply = \"apply\",\n concat = \"concat\",\n //taken from Modernizr touch test: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js#L40\n supportsTouch = ('ontouchstart' in window) || window.TouchEvent || window.DocumentTouch && document instanceof DocumentTouch,\n E = \"\",\n S = \" \",\n Str = String,\n split = \"split\",\n events = \"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[split](S),\n touchMap = {\n mousedown: \"touchstart\",\n mousemove: \"touchmove\",\n mouseup: \"touchend\"\n },\n lowerCase = Str.prototype.toLowerCase,\n math = Math,\n mmax = math.max,\n mmin = math.min,\n abs = math.abs,\n pow = math.pow,\n PI = math.PI,\n nu = \"number\",\n str
57590ing = \"string\",\n array = \"array\",\n toString = \"toString\",\n fillString = \"fill\",\n objectToString = Object.prototype.toString,\n paper = {},\n push = \"push\",\n ISURL = R._ISURL = /^url\\(['\"]?(.+?)['\"]?\\)$/i,\n colourRegExp = /^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i,\n isnan = {\"NaN\": 1, \"Infinity\": 1, \"-Infinity\": 1},\n bezierrg = /^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,\n round = math.round,\n setAttribute = \"setAttribute\",\n toFloat = parseFloat,\n toInt = parseInt,\n upperCase = Str.prototype.toUpperCase,\n availableAttrs = R._availableAttrs = {\n \"arrow-end\": \"none\",\n \"arrow-start\": \"none\",\n blur: 0,\n \"clip-rect\": \"0 0 1e9 1e9\",\n cursor: \"default\",\n cx: 0,\n cy: 0,\n fill: \"#fff\",\n \"fill-opacity\": 1,\n font: '10px \"Arial\"',\n \"font-family\": '\"Arial\"',\n \"font-size\": \"10\",\n \"font-style\": \"normal\",\n \"font-weight\"
57590: 400,\n gradient: 0,\n height: 0,\n href: \"http://raphaeljs.com/\",\n \"letter-spacing\": 0,\n opacity: 1,\n path: \"M0,0\",\n r: 0,\n rx: 0,\n ry: 0,\n src: \"\",\n stroke: \"#000\",\n \"stroke-dasharray\": \"\",\n \"stroke-linecap\": \"butt\",\n \"stroke-linejoin\": \"butt\",\n \"stroke-miterlimit\": 0,\n \"stroke-opacity\": 1,\n \"stroke-width\": 1,\n target: \"_blank\",\n \"text-anchor\": \"middle\",\n title: \"Raphael\",\n transform: \"\",\n width: 0,\n x: 0,\n y: 0,\n \"class\": \"\"\n },\n availableAnimAttrs = R._availableAnimAttrs = {\n blur: nu,\n \"clip-rect\": \"csv\",\n cx: nu,\n cy: nu,\n fill: \"colour\",\n \"fill-opacity\": nu,\n \"font-size\": nu,\n height: nu,\n opacity: nu,\n path: \"path\",\n r: nu,\n rx: nu,\n ry: nu,\n stroke: \"colour\",\n \"stroke-opacity\": nu,\n \"stroke-width\": nu,\n transform: \"transform\",\n width: nu,\n x: nu,\n y: nu\n },\n whitespace = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]/g,\n commaSpaces = /[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,\n hsrg = {hs: 1, rg: 1},\n p2s = /,?([achlmqrstvxz]),?/gi,\n pathCommand = /([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n tCommand = /([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/ig,\n pathValues = /(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/ig,\n radial_gradient = R._radial_gradient = /^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,\n eldata = {},\n sortByKey = function (a, b) {\n return a.key - b.key;\n },\n sortByNumber = function (a, b) {\n return toFloat(a) - toFloat(b);\n },\n fun = function () {},\n pipe = function (x) {\n return x;\n },\n rectPath = R._rectPath = function (x, y, w, h, r) {\n if (r) {\n return [[\"M\", x + r, y], [\"l\", w - r * 2, 0], [\"a\", r, r, 0, 0, 1, r, r], [\"l\", 0, h - r * 2], [\"a\", r, r, 0, 0, 1, -r, r], [\"l\", r * 2 - w, 0], [\"a\", r, r, 0, 0, 1, -r, -r], [\"l\", 0, r * 2 - h], [\"a\", r, r, 0, 0, 1, r, -r], [\"z\"]];\n }\n return [[\"M\", x, y], [\"l\", w, 0], [\"l\", 0, h], [\"l\", -w, 0], [\"z\"]];\n },\n ellipsePath = function (x, y, rx, ry) {\n if (ry == null) {\n ry = rx;\n }\n return [[\"M\", x, y], [\"m\", 0, -ry], [\"a\", rx, ry, 0, 1, 1, 0, 2 * ry], [\"a\", rx, ry, 0, 1, 1, 0, -2 * ry], [\"z\"]];\n },\n getPath = R._getPath = {\n path: function (el) {\n return el.attr(\"path\");\n },\n circle: function (el) {\n var a = el.attrs;\n return ellipsePath(a.cx, a.cy, a.r);\n },\n ellipse: function (el) {\n var a = el.attrs;\n return ellipsePath(a.cx, a.cy, a.rx, a.ry);\n },\n rect: function (el) {\n var a = el.attrs;\n return rectPath(a.x, a.y, a.width, a.height, a.r);\n },\n image: function (el) {\n var a = el.attrs;\n return rectPath(a.x, a.y, a.width, a.height);\n },\n text: function (el) {\n var bbox = el._getBBox();\n return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n },\n set : function(el) {\n var bbox = el._getBBox();\n return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);\n }\n },\n /*\\\n * Raphael.mapPath\n [ method ]\n **\n * Transform the path string with given matrix.\n > Parameters\n - path (string) path string\n - matrix (object) see @Matrix\n = (string) transformed path string\n \\*/\n mapPath = R.mapPath = function (path, matrix) {\n if (!matrix) {\n return path;\n }\n var x, y, i, j, ii, jj, pathi;\n path = path2curve(path);\n for (i = 0, ii = path.length; i < ii;
57590 i++) {\n pathi = path[i];\n for (j = 1, jj = pathi.length; j < jj; j += 2) {\n x = matrix.x(pathi[j], pathi[j + 1]);\n y = matrix.y(pathi[j], pathi[j + 1]);\n pathi[j] = x;\n pathi[j + 1] = y;\n }\n }\n return path;\n };\n\n R._g = g;\n /*\\\n * Raphael.type\n [ property (string) ]\n **\n * Can be âSVGâ, âVMLâ or empty, depending on browser support.\n \\*/\n R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\", \"1.1\") ? \"SVG\" : \"VML\");\n if (R.type == \"VML\") {\n var d = g.doc.createElement(\"div\"),\n b;\n d.innerHTML = '<v:shape adj=\"1\"/>';\n b = d.firstChild;\n b.style.behavior = \"url(#default#VML)\";\n if (!(b && typeof b.adj == \"object\")) {\n return (R.type = E);\n }\n d = null;\n }\n /*\\\n * Raphael.svg\n [ property (boolean) ]\n **\n * `true` if browser supports SVG.\n \\*/\n /*\\\n * Raphael.vml\n [ property (boolean) ]\n **\n * `true` if browser supports VML.\n \\*/\n R.svg = !(R.vml = R.type == \"VML\");\n R._Paper = Paper;\n /*\\\n * Raphael.fn\n [ property (object) ]\n **\n * You can add your own method to the canvas. For example if you want to draw a pie chart,\n * you can create your own pie chart function and ship it as a Raphaël plugin. To do this\n * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a\n * Raphaël instance is created, otherwise it will take no effect. Please note that the\n * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to\n * ensure any namespacing ensures proper context.\n > Usage\n | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {\n | return this.path( ... );\n | };\n | // or create namespace\n | Raphael.fn.mystuff = {\n | arrow: function () {â¦},\n | star: function () {â¦},\n | // etcâ¦\n | };\n | var paper = Raphael(10, 10, 630, 480);\n | // then use it\n | paper.arrow(10, 10, 30, 30, 5).attr({fill: \"#f00\"});\n | paper.mystuff.arrow();\n | paper.mystuff.star();\n \\*/\n R.fn = paperproto = Paper.prototype = R.prototype;\n R._id = 0;\n /*\\\n * Raphael.is\n [ method ]\n **\n * Handful of replacements for `typeof` operator.\n > Parameters\n - o (â¦) any object or primitive\n - type (string) name of the type, i.e. âstringâ, âfunctionâ, ânumberâ, etc.\n = (boolean) is given value is of given type\n \\*/\n R.is = function (o, type) {\n type = lowerCase.call(type);\n if (type == \"finite\") {\n return !isnan[has](+o);\n }\n if (type == \"array\") {\n return o instanceof Array;\n }\n return (type == \"null\" && o === null) ||\n (type == typeof o && o !== null) ||\n (type == \"object\" && o === Object(o)) ||\n (type == \"array\" && Array.isArray && Array.isArray(o)) ||\n objectToString.call(o).slice(8, -1).toLowerCase() == type;\n };\n\n function clone(obj) {\n if (typeof obj == \"function\" || Object(obj) !== obj) {\n return obj;\n }\n var res = new obj.constructor;\n for (var key in obj) if (obj[has](key)) {\n res[key] = clone(obj[key]);\n }\n return res;\n }\n\n /*\\\n * Raphael.angle\n [ method ]\n **\n * Returns angle between two or three points\n > Parameters\n - x1 (number) x coord of first point\n - y1 (number) y coord of first point\n - x2 (number) x coord of second point\n - y2 (number) y coord of second point\n - x3 (number) #optional x coord of third point\n - y3 (number) #optional y coord of third point\
57590n = (number) angle in degrees.\n \\*/\n R.angle = function (x1, y1, x2, y2, x3, y3) {\n if (x3 == null) {\n var x = x1 - x2,\n y = y1 - y2;\n if (!x && !y) {\n return 0;\n }\n return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;\n } else {\n return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);\n }\n };\n /*\\\n * Raphael.rad\n [ method ]\n **\n * Transform angle to radians\n > Parameters\n - deg (number) angle in degrees\n = (number) angle in radians.\n \\*/\n R.rad = function (deg) {\n return deg % 360 * PI / 180;\n };\n /*\\\n * Raphael.deg\n [ method ]\n **\n * Transform angle to degrees\n > Parameters\n - rad (number) angle in radians\n = (number) angle in degrees.\n \\*/\n R.deg = function (rad) {\n return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;\n };\n /*\\\n * Raphael.snapTo\n [ method ]\n **\n * Snaps given value to given grid.\n > Parameters\n - values (array|number) given array of values or step of the grid\n - value (number) value to adjust\n - tolerance (number) #optional tolerance for snapping. Default is `10`.\n = (number) adjusted value.\n \\*/\n R.snapTo = function (values, value, tolerance) {\n tolerance = R.is(tolerance, \"finite\") ? tolerance : 10;\n if (R.is(values, array)) {\n var i = values.length;\n while (i--) if (abs(values[i] - value) <= tolerance) {\n return values[i];\n }\n } else {\n values = +values;\n var rem = value % values;\n if (rem < tolerance) {\n return value - rem;\n }\n if (rem > values - tolerance) {\n return value - rem + values;\n }\n }\n return value;\n };\n\n /*\\\n * Raphael.createUUID\n [ method ]\n **\n * Returns RFC4122, version 4 ID\n \\*/\n var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {\n return function () {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(uuidRegEx, uuidReplacer).toUpperCase();\n };\n })(/[xy]/g, function (c) {\n var r = math.random() * 16 | 0,\n v = c == \"x\" ? r : (r & 3 | 8);\n return v.toString(16);\n });\n\n /*\\\n * Raphael.setWindow\n [ method ]\n **\n * Used when you need to draw in `<iframe>`. Switched window to the iframe one.\n > Parameters\n - newwin (window) new window object\n \\*/\n R.setWindow = function (newwin) {\n eve(\"raphael.setWindow\", R, g.win, newwin);\n g.win = newwin;\n g.doc = g.win.document;\n if (R._engine.initWin) {\n R._engine.initWin(g.win);\n }\n };\n var toHex = function (color) {\n if (R.vml) {\n // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/\n var trim = /^\\s+|\\s+$/g;\n var bod;\n try {\n var docum = new ActiveXObject(\"htmlfile\");\n docum.write(\"<body>\");\n docum.close();\n bod = docum.body;\n } catch(e) {\n bod = createPopup().document.body;\n }\n var range = bod.createTextRange();\n toHex = cacher(function (color) {\n try {\n bod.style.color = Str(color).replace(trim, E);\n var value = range.queryCommandValue(\"ForeColor\");\n value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);\n return \"#\" + (\"000000\" + value.toString(16)).slice(-6);\n } catch(e) {\n return \"none\";\n }\n });\n } else {\n var i = g.doc.createElement(\"i\");\n i.title = \"Rapha\\xebl Colour Picker\";\n i.style.display = \"none\";\n g.doc.body.appendChild(i);
57590\n toHex = cacher(function (color) {\n i.style.color = color;\n return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue(\"color\");\n });\n }\n return toHex(color);\n },\n hsbtoString = function () {\n return \"hsb(\" + [this.h, this.s, this.b] + \")\";\n },\n hsltoString = function () {\n return \"hsl(\" + [this.h, this.s, this.l] + \")\";\n },\n rgbtoString = function () {\n return this.hex;\n },\n prepareRGB = function (r, g, b) {\n if (g == null && R.is(r, \"object\") && \"r\" in r && \"g\" in r && \"b\" in r) {\n b = r.b;\n g = r.g;\n r = r.r;\n }\n if (g == null && R.is(r, string)) {\n var clr = R.getRGB(r);\n r = clr.r;\n g = clr.g;\n b = clr.b;\n }\n if (r > 1 || g > 1 || b > 1) {\n r /= 255;\n g /= 255;\n b /= 255;\n }\n\n return [r, g, b];\n },\n packageRGB = function (r, g, b, o) {\n r *= 255;\n g *= 255;\n b *= 255;\n var rgb = {\n r: r,\n g: g,\n b: b,\n hex: R.rgb(r, g, b),\n toString: rgbtoString\n };\n R.is(o, \"finite\") && (rgb.opacity = o);\n return rgb;\n };\n\n /*\\\n * Raphael.color\n [ method ]\n **\n * Parses the color string and returns object with all values for the given color.\n > Parameters\n - clr (string) color string in one of the supported formats (see @Raphael.getRGB)\n = (object) Combined RGB & HSB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #â¢â¢â¢â¢â¢â¢,\n o error (boolean) `true` if string canât be parsed,\n o h (number) hue,\n o s (number) saturation,\n o v (number) value (brightness),\n o l (number) lightness\n o }\n \\*/\n R.color = function (clr) {\n var rgb;\n if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"b\" in clr) {\n rgb = R.hsb2rgb(clr);\n clr.r = rgb.r;\n clr.g = rgb.g;\n clr.b = rgb.b;\n clr.hex = rgb.hex;\n } else if (R.is(clr, \"object\") && \"h\" in clr && \"s\" in clr && \"l\" in clr) {\n rgb = R.hsl2rgb(clr);\n clr.r = rgb.r;\n clr.g = rgb.g;\n clr.b = rgb.b;\n clr.hex = rgb.hex;\n } else {\n if (R.is(clr, \"string\")) {\n clr = R.getRGB(clr);\n }\n if (R.is(clr, \"object\") && \"r\" in clr && \"g\" in clr && \"b\" in clr) {\n rgb = R.rgb2hsl(clr);\n clr.h = rgb.h;\n clr.s = rgb.s;\n clr.l = rgb.l;\n rgb = R.rgb2hsb(clr);\n clr.v = rgb.b;\n } else {\n clr = {hex: \"none\"};\n clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;\n }\n }\n clr.toString = rgbtoString;\n return clr;\n };\n /*\\\n * Raphael.hsb2rgb\n [ method ]\n **\n * Converts HSB values to RGB object.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - v (number) value or brightness\n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #â¢â¢â¢â¢â¢â¢\n o }\n \\*/\n R.hsb2rgb = function (h, s, v, o) {\n if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"b\" in h) {\n v = h.b;\n s = h.s;\n o = h.o;\n h = h.h;\n }\n h *= 360;\n var R, G, B, X, C;\n h = (h % 360) / 60;\n C = v * s;\n X = C * (1 - abs(h % 2 - 1));\n R = G = B = v - C;\n\n h = ~~h;\n R += [C, X, 0, 0, X, C][h];\n G += [X, C, C, X, 0, 0][h];\n B += [0, 0, X, C, C, X][h];\n return packageRGB(R, G, B, o);\n };\n /*\\\n * Raphael.hsl2rgb\n [ method ]\n **\n * Converts HSL values to RGB object.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - l (number) luminosity\n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue,\n o hex (string) color in HTML/CSS format: #â¢â¢â¢â¢â¢â¢\n o }\n \\*/\n R.hsl2rgb = function (h, s, l, o) {\n if (this.is(h, \"object\") && \"h\" in h && \"s\" in h && \"l\" in h) {\n l = h.l;\n s = h.s;\n h = h.h;\n }\n if (h > 1 || s > 1 || l > 1) {\n h /= 360;\n s /= 100;\n l /= 100;\n }\n h *= 360;\n var R, G, B, X, C;\n h = (h % 360) / 60;\n C = 2 * s * (l < .5 ? l : 1 - l);\n X = C * (1 - abs(h % 2 - 1));\n R = G = B = l - C / 2;\n\n h = ~~h;\n R += [C, X, 0, 0, X, C][h];\n G += [X, C, C, X, 0, 0][h];\n B += [0, 0, X, C, C, X][h];\n return packageRGB(R, G, B, o);\n };\n /*\\\n * Raphael.rgb2hsb\n [ method ]\n **\n * Converts RGB values to HSB object.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (object) HSB object in format:\n o {\n o h (number) hue\n o s (number) saturation\n o b (number) brightness\n o }\n \\*/\n R.rgb2hsb = function (r, g, b) {\n b = prepareRGB(r, g, b);\n r = b[0];\n g = b[1];\n b = b[2];\n\n var H, S, V, C;\n V = mmax(r, g, b);\n C = V - mmin(r, g, b);\n H = (C == 0 ? null :\n V == r ? (g - b) / C :\n V == g ? (b - r) / C + 2 :\n (r - g) / C + 4\n );\n H = ((H + 360) % 6) * 60 / 360;\n S = C == 0 ? 0 : C / V;\n return {h: H, s: S, b: V, toString: hsbtoString};\n };\n /*\\\n * Raphael.rgb2hsl\n [ method ]\n **\n * Converts RGB values to HSL object.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (object) HSL object in format:\n o {\n o h (number) hue\n o s (number) saturation\n o l (number) luminosity\n o }\n \\*/\n R.rgb2hsl = function (r, g, b) {\n b = prepareRGB(r, g, b);\n r = b[0];\n g = b[1];\n b = b[2];\n\n var H, S, L, M, m, C;\n M = mmax(r, g, b);\n m = mmin(r, g, b);\n C = M - m;\n H = (C == 0 ? null :\n M == r ? (g - b) / C :\n M == g ? (b - r) / C + 2 :\n (r - g) / C + 4);\n H = ((H + 360) % 6) * 60 / 360;\n L = (M + m) / 2;\n S = (C == 0 ? 0 :\n L < .5 ? C / (2 * L) :\n C / (2 - 2 * L));\n return {h: H, s: S, l: L, toString: hsltoString};\n };\n R._path2string = function () {\n return this.join(\",\").replace(p2s, \"$1\");\n };\n function repush(array, item) {\n for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {\n return array.push(array.splice(i, 1)[0]);\n }\n }\n function cacher(f, scope, postprocessor) {\n function newf() {\n var arg = Array.prototype.slice.call(arguments, 0),\n args = arg.join(\"\\u2400\"),\n cache = newf.cache = newf.cache || {},\n count = newf.count = newf.count || [];\n if (cache[has](args)) {\n repush(count, args);\n return postprocessor ? postprocessor(cache[args]) : cache[args];\n }\n count.length >= 1e3 && delete cache[count.shift()];\n count.push(args);\n cache[args] = f[apply](scope, arg);\n return postprocessor ? postprocessor(cache[args]) : cache[args];\n }\n return newf;\n }\n\n var preload = R._preload = function (src, f) {\n var img = g.doc.createElement(\"img\");\n img.style.cssText = \"position:absolute;
57590left:-9999em;top:-9999em\";\n img.onload = function () {\n f.call(this);\n this.onload = null;\n g.doc.body.removeChild(this);\n };\n img.onerror = function () {\n g.doc.body.removeChild(this);\n };\n g.doc.body.appendChild(img);\n img.src = src;\n };\n\n function clrToString() {\n return this.hex;\n }\n\n /*\\\n * Raphael.getRGB\n [ method ]\n **\n * Parses colour string as RGB object\n > Parameters\n - colour (string) colour string in one of formats:\n # <ul>\n # <li>Colour name (â<code>red</code>â, â<code>green</code>â, â<code>cornflowerblue</code>â, etc)</li>\n # <li>#â¢â¢â¢ â shortened HTML colour: (â<code>#000</code>â, â<code>#fc0</code>â, etc)</li>\n # <li>#â¢â¢â¢â¢â¢â¢ â full length HTML colour: (â<code>#000000</code>â, â<code>#bd2300</code>â)</li>\n # <li>rgb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â red, green and blue channelsâ values: (â<code>rgb(200, 100, 0)</code>â)</li>\n # <li>rgb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgb(100%, 175%, 0%)</code>â)</li>\n # <li>hsb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â hue, saturation and brightness values: (â<code>hsb(0.5, 0.25, 1)</code>â)</li>\n # <li>hsb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %</li>\n # <li>hsl(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â same as hsb</li>\n # <li>hsl(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as hsb</li>\n # </ul>\n = (object) RGB object in format:\n o {\n o r (number) red,\n o g (number) green,\n o b (number) blue\n o hex (string) color in HTML/CSS format: #â¢â¢â¢â¢â¢â¢,\n o error (boolean) true if string canât be parsed\n o }\n \\*/\n R.getRGB = cacher(function (colour) {\n if (!colour || !!((colour = Str(colour)).indexOf(\"-\") + 1)) {\n return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n }\n if (colour == \"none\") {\n return {r: -1, g: -1, b: -1, hex: \"none\", toString: clrToString};\n }\n !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == \"#\") && (colour = toHex(colour));\n var res,\n red,\n green,\n blue,\n opacity,\n t,\n values,\n rgb = colour.match(colourRegExp);\n if (rgb) {\n if (rgb[2]) {\n blue = toInt(rgb[2].substring(5), 16);\n green = toInt(rgb[2].substring(3, 5), 16);\n red = toInt(rgb[2].substring(1, 3), 16);\n }\n if (rgb[3]) {\n blue = toInt((t = rgb[3].charAt(3)) + t, 16);\n green = toInt((t = rgb[3].charAt(2)) + t, 16);\n red = toInt((t = rgb[3].charAt(1)) + t, 16);\n }\n if (rgb[4]) {\n values = rgb[4][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n rgb[1].toLowerCase().slice(0, 4) == \"rgba\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n }\n if (rgb[5]) {\n values = rgb[5][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n rgb[1].toLowerCase().slice(0, 4) == \"hsba\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n return R.hsb2rgb(red, green, blue, opacity);\n }\n if (rgb[6]) {\n values = rgb[6][split](commaSpaces);\n red = toFloat(values[0]);\n values[0].slice(-1) == \"%\" && (red *= 2.55);\n green = toFloat(values[1]);\n values[1].slice(-1) == \"%\" && (green *= 2.55);\n blue = toFloat(values[2]);\n values[2].slice(-1) == \"%\" && (blue *= 2.55);\n (values[0].slice(-3) == \"deg\" || values[0].slice(-1) == \"\\xb0\") && (red /= 360);\n rgb[1].toLowerCase().slice(0, 4) == \"hsla\" && (opacity = toFloat(values[3]));\n values[3] && values[3].slice(-1) == \"%\" && (opacity /= 100);\n return R.hsl2rgb(red, green, blue, opacity);\n }\n rgb = {r: red, g: green, b: blue, toString: clrToString};\n rgb.hex = \"#\" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);\n R.is(opacity, \"finite\") && (rgb.opacity = opacity);\n return rgb;\n }\n return {r: -1, g: -1, b: -1, hex: \"none\", error: 1, toString: clrToString};\n }, R);\n /*\\\n * Raphael.hsb\n [ method ]\n **\n * Converts HSB values to hex representation of the colour.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - b (number) value or brightness\n = (string) hex representation of the colour.\n \\*/\n R.hsb = cacher(function (h, s, b) {\n return R.hsb2rgb(h, s, b).hex;\n });\n /*\\\n * Raphael.hsl\n [ method ]\n **\n * Converts HSL values to hex representation of the colour.\n > Parameters\n - h (number) hue\n - s (number) saturation\n - l (number) luminosity\n = (string) hex representation of the colour.\n \\*/\n R.hsl = cacher(function (h, s, l) {\n return R.hsl2rgb(h, s, l).hex;\n });\n /*\\\n * Raphael.rgb\n [ method ]\n **\n * Converts RGB values to hex representation of the colour.\n > Parameters\n - r (number) red\n - g (number) green\n - b (number) blue\n = (string) hex representation of the colour.\n \\*/\n R.rgb = cacher(function (r, g, b) {\n function round(x) { return (x + 0.5) | 0; }\n return \"#\" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);\n });\n /*\\\n * Raphael.getColor\n [ method ]\n **\n * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset\n > Parameters\n - value (number) #optional brightness, default is `0.75`\n = (string) hex representation of the colour.\n \\*/\n R.getColor = function (value) {\n var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},\n rgb = this.hsb2rgb(start.h, start.s, start.b);\n start.h += .075;\n if (start.h > 1) {\n start.h = 0;\n start.s -= .2;\n start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});\n }\n return rgb.hex;\n };\n /*\\\n * Raphael.getColor.reset\n [ method ]\n **\n * Resets spectrum position for @Raphael.getColor back to red.\n \\*/\n R.getColor.reset = function () {\n delete this.start;\n };\n\n // http://schepers.cc/getting-to-the-point\n function catmullRom2bezier(crp, z) {\n var d = [];\n for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {\n var p = [\n {x: +crp[i - 2], y: +crp[i - 1]},\n {x: +crp[i], y: +crp[i + 1]},\n {x: +crp[i + 2], y: +crp[i + 3]},\n {x: +crp[i + 4], y: +crp[i + 5]}\n ];\n if (z) {\n if (!i) {\n p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};\n } else if (iLen - 4 == i) {\n p[3] = {x: +crp[0], y: +crp[1]};\n }
57590 else if (iLen - 2 == i) {\n p[2] = {x: +crp[0], y: +crp[1]};\n p[3] = {x: +crp[2], y: +crp[3]};\n }\n } else {\n if (iLen - 4 == i) {\n p[3] = p[2];\n } else if (!i) {\n p[0] = {x: +crp[i], y: +crp[i + 1]};\n }\n }\n d.push([\"C\",\n (-p[0].x + 6 * p[1].x + p[2].x) / 6,\n (-p[0].y + 6 * p[1].y + p[2].y) / 6,\n (p[1].x + 6 * p[2].x - p[3].x) / 6,\n (p[1].y + 6*p[2].y - p[3].y) / 6,\n p[2].x,\n p[2].y\n ]);\n }\n\n return d;\n }\n /*\\\n * Raphael.parsePathString\n [ method ]\n **\n * Utility method\n **\n * Parses given path string into an array of arrays of path segments.\n > Parameters\n - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)\n = (array) array of segments.\n \\*/\n R.parsePathString = function (pathString) {\n if (!pathString) {\n return null;\n }\n var pth = paths(pathString);\n if (pth.arr) {\n return pathClone(pth.arr);\n }\n\n var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},\n data = [];\n if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption\n data = pathClone(pathString);\n }\n if (!data.length) {\n Str(pathString).replace(pathCommand, function (a, b, c) {\n var params = [],\n name = b.toLowerCase();\n c.replace(pathValues, function (a, b) {\n b && params.push(+b);\n });\n if (name == \"m\" && params.length > 2) {\n data.push([b][concat](params.splice(0, 2)));\n name = \"l\";\n b = b == \"m\" ? \"l\" : \"L\";\n }\n if (name == \"r\") {\n data.push([b][concat](params));\n } else while (params.length >= paramCounts[name]) {\n data.push([b][concat](params.splice(0, paramCounts[name])));\n if (!paramCounts[name]) {\n break;\n }\n }\n });\n }\n data.toString = R._path2string;\n pth.arr = pathClone(data);\n return data;\n };\n /*\\\n * Raphael.parseTransformString\n [ method ]\n **\n * Utility method\n **\n * Parses given path string into an array of transformations.\n > Parameters\n - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)\n = (array) array of transformations.\n \\*/\n R.parseTransformString = cacher(function (TString) {\n if (!TString) {\n return null;\n }\n var paramCounts = {r: 3, s: 4, t: 2, m: 6},\n data = [];\n if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption\n data = pathClone(TString);\n }\n if (!data.length) {\n Str(TString).replace(tCommand, function (a, b, c) {\n var params = [],\n name = lowerCase.call(b);\n c.replace(pathValues, function (a, b) {\n b && params.push(+b);\n });\n data.push([b][concat](params));\n });\n }\n data.toString = R._path2string;\n return data;\n }, this, function(elem) {\n if (!elem) return elem;\n var newData = [];\n for (var i = 0; i < elem.length; i++) {\n var newLevel = [];\n for (var j = 0; j < elem[i].length; j++) {\n newLevel.push(elem[i][j]);\n }\n newData.push(newLevel);\n }\n return newData; } );\n // PATHS\n var paths = function (ps) {\n var p = paths.ps = paths.ps || {};\n if (p[ps]) {\n p[ps].sleep = 100;\n } else {\n p[ps] = {\n sleep: 100\n };\n }\n setTimeout(function () {\n for (var key in p) if (p[has](key) && key != ps) {\n p[key].sleep--;\n !p[key].sleep && delete p[key];\n }\n });\n return p[ps];\n };\n /*\\\n * Raphael.findDotsAtSegment\n [ method ]\n **\n * Utility method\n **\n * Find dot coordinates on the given cubic bezier curve at the given t.\n > Parameters\n - p1x (number) x of the first point of the curve\
57590n - p1y (number) y of the first point of the curve\n - c1x (number) x of the first anchor of the curve\n - c1y (number) y of the first anchor of the curve\n - c2x (number) x of the second anchor of the curve\n - c2y (number) y of the second anchor of the curve\n - p2x (number) x of the second point of the curve\n - p2y (number) y of the second point of the curve\n - t (number) position on the curve (0..1)\n = (object) point information in format:\n o {\n o x: (number) x coordinate of the point\n o y: (number) y coordinate of the point\n o m: {\n o x: (number) x coordinate of the left anchor\n o y: (number) y coordinate of the left anchor\n o }\n o n: {\n o x: (number) x coordinate of the right anchor\n o y: (number) y coordinate of the right anchor\n o }\n o start: {\n o x: (number) x coordinate of the start of the curve\n o y: (number) y coordinate of the start of the curve\n o }\n o end: {\n o x: (number) x coordinate of the end of the curve\n o y: (number) y coordinate of the end of the curve\n o }\n o alpha: (number) angle of the curve derivative at the point\n o }\n \\*/\n R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n var t1 = 1 - t,\n t13 = pow(t1, 3),\n t12 = pow(t1, 2),\n t2 = t * t,\n t3 = t2 * t,\n x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,\n y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,\n mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),\n my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),\n nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),\n ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),\n ax = t1 * p1x + t * c1x,\n ay = t1 * p1y + t * c1y,\n cx = t1 * c2x + t * p2x,\n cy = t1 * c2y + t * p2y,\n alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);\n (mx > nx || my < ny) && (alpha += 180);\n return {\n x: x,\n y: y,\n m: {x: mx, y: my},\n n: {x: nx, y: ny},\n start: {x: ax, y: ay},\n end: {x: cx, y: cy},\n alpha: alpha\n };\n };\n /*\\\n * Raphael.bezierBBox\n [ method ]\n **\n * Utility method\n **\n * Return bounding box of a given cubic bezier curve\n > Parameters\n - p1x (number) x of the first point of the curve\n - p1y (number) y of the first point of the curve\n - c1x (number) x of the first anchor of the curve\n - c1y (number) y of the first anchor of the curve\n - c2x (number) x of the second anchor of the curve\n - c2y (number) y of the second anchor of the curve\n - p2x (number) x of the second point of the curve\n - p2y (number) y of the second point of the curve\n * or\n - bez (array) array of six points for bezier curve\n = (object) point information in format:\n o {\n o min: {\n o x: (number) x coordinate of the left point\n o y: (number) y coordinate of the top point\n o }\n o max: {\n o x: (number) x coordinate of the right point\n o y: (number) y coordinate of the bottom point\n o }\n o }\n \\*/\n R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n if (!R.is(p1x, \"array\")) {\n p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];\n }\n var bbox = curveDim.apply(null, p1x);\n return {\n x: bbox.min.x,\n y: bbox.min.y,\n x2: bbox.max.x,\n y2: bbox.max.y,\n width: bbox.max.x - bbox.min.x,\n height: bbox.max.y - bbox.min.y\n };\n };\n /*\\\n * Raphael.isPointInsideBBox\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if given point is inside bounding boxes.\n > Parameters\n - bbox (string) bounding box\n - x (string) x coordinate of the point\n - y (string) y co
57590ordinate of the point\n = (boolean) `true` if point inside\n \\*/\n R.isPointInsideBBox = function (bbox, x, y) {\n return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;\n };\n /*\\\n * Raphael.isBBoxIntersect\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if two bounding boxes intersect\n > Parameters\n - bbox1 (string) first bounding box\n - bbox2 (string) second bounding box\n = (boolean) `true` if they intersect\n \\*/\n R.isBBoxIntersect = function (bbox1, bbox2) {\n var i = R.isPointInsideBBox;\n return i(bbox2, bbox1.x, bbox1.y)\n || i(bbox2, bbox1.x2, bbox1.y)\n || i(bbox2, bbox1.x, bbox1.y2)\n || i(bbox2, bbox1.x2, bbox1.y2)\n || i(bbox1, bbox2.x, bbox2.y)\n || i(bbox1, bbox2.x2, bbox2.y)\n || i(bbox1, bbox2.x, bbox2.y2)\n || i(bbox1, bbox2.x2, bbox2.y2)\n || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)\n && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);\n };\n function base3(t, p1, p2, p3, p4) {\n var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,\n t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;\n return t * t2 - 3 * p1 + 3 * p2;\n }\n function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {\n if (z == null) {\n z = 1;\n }\n z = z > 1 ? 1 : z < 0 ? 0 : z;\n var z2 = z / 2,\n n = 12,\n Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],\n Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],\n sum = 0;\n for (var i = 0; i < n; i++) {\n var ct = z2 * Tvalues[i] + z2,\n xbase = base3(ct, x1, x2, x3, x4),\n ybase = base3(ct, y1, y2, y3, y4),\n comb = xbase * xbase + ybase * ybase;\n sum += Cvalues[i] * math.sqrt(comb);\n }\n return z2 * sum;\n }\n function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {\n if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {\n return;\n }\n var t = 1,\n step = t / 2,\n t2 = t - step,\n l,\n e = .01;\n l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n while (abs(l - ll) > e) {\n step /= 2;\n t2 += (l < ll ? 1 : -1) * step;\n l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);\n }\n return t2;\n }\n function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {\n if (\n mmax(x1, x2) < mmin(x3, x4) ||\n mmin(x1, x2) > mmax(x3, x4) ||\n mmax(y1, y2) < mmin(y3, y4) ||\n mmin(y1, y2) > mmax(y3, y4)\n ) {\n return;\n }\n var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),\n ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),\n denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);\n\n if (!denominator) {\n return;\n }\n var px = nx / denominator,\n py = ny / denominator,\n px2 = +px.toFixed(2),\n py2 = +py.toFixed(2);\n if (\n px2 < +mmin(x1, x2).toFixed(2) ||\n px2 > +mmax(x1, x2).toFixed(2) ||\n px2 < +mmin(x3, x4).toFixed(2) ||\n px2 > +mmax(x3, x4).toFixed(2) ||\n py2 < +mmin(y1, y2).toFixed(2) ||\n py2 > +mmax(y1, y2).toFixed(2) ||\n py2 < +mmin(y3, y4).toFixed(2) ||\n py2 > +mmax(y3, y4).toFixed(2)\n ) {\n return;\n }\n return {x: px, y: py};\n }\n function inter(bez1, bez2) {\n return interHelper(bez1, bez2);\n }\n function interCount(bez1, bez2) {\n return interHelper(bez1, bez2, 1);\n }\n function interHelper(bez1, bez2, justCount) {\n var bbox1 = R.bezierBBox(bez1),\n bbox2 = R.bezierBBox(bez2);\n if (!R.isBBoxIntersect(bbox1, bbox2)) {\n return justCount ? 0 : [];\n }\n var l1 = bezlen.apply(0, bez1),\n l2 = bezlen.apply(0, bez2),\n n1 = mmax(~~(l1 / 5), 1),\
57590n n2 = mmax(~~(l2 / 5), 1),\n dots1 = [],\n dots2 = [],\n xy = {},\n res = justCount ? 0 : [];\n for (var i = 0; i < n1 + 1; i++) {\n var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));\n dots1.push({x: p.x, y: p.y, t: i / n1});\n }\n for (i = 0; i < n2 + 1; i++) {\n p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));\n dots2.push({x: p.x, y: p.y, t: i / n2});\n }\n for (i = 0; i < n1; i++) {\n for (var j = 0; j < n2; j++) {\n var di = dots1[i],\n di1 = dots1[i + 1],\n dj = dots2[j],\n dj1 = dots2[j + 1],\n ci = abs(di1.x - di.x) < .001 ? \"y\" : \"x\",\n cj = abs(dj1.x - dj.x) < .001 ? \"y\" : \"x\",\n is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);\n if (is) {\n if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {\n continue;\n }\n xy[is.x.toFixed(4)] = is.y.toFixed(4);\n var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),\n t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);\n if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {\n if (justCount) {\n res++;\n } else {\n res.push({\n x: is.x,\n y: is.y,\n t1: mmin(t1, 1),\n t2: mmin(t2, 1)\n });\n }\n }\n }\n }\n }\n return res;\n }\n /*\\\n * Raphael.pathIntersection\n [ method ]\n **\n * Utility method\n **\n * Finds intersections of two paths\n > Parameters\n - path1 (string) path string\n - path2 (string) path string\n = (array) dots of intersection\n o [\n o {\n o x: (number) x coordinate of the point\n o y: (number) y coordinate of the point\n o t1: (number) t value for segment of path1\n o t2: (number) t value for segment of path2\n o segment1: (number) order number for segment of path1\n o segment2: (number) order number for segment of path2\n o bez1: (array) eight coordinates representing beziér curve for the segment of path1\n o bez2: (array) eight coordinates representing beziér curve for the segment of path2\n o }\n o ]\n \\*/\n R.pathIntersection = function (path1, path2) {\n return interPathHelper(path1, path2);\n };\n R.pathIntersectionNumber = function (path1, path2) {\n return interPathHelper(path1, path2, 1);\n };\n function interPathHelper(path1, path2, justCount) {\n path1 = R._path2curve(path1);\n path2 = R._path2curve(path2);\n var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,\n res = justCount ? 0 : [];\n for (var i = 0, ii = path1.length; i < ii; i++) {\n var pi = path1[i];\n if (pi[0] == \"M\") {\n x1 = x1m = pi[1];\n y1 = y1m = pi[2];\n } else {\n if (pi[0] == \"C\") {\n bez1 = [x1, y1].concat(pi.slice(1));\n x1 = bez1[6];\n y1 = bez1[7];\n } else {\n bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];\n x1 = x1m;\n y1 = y1m;\n }\n for (var j = 0, jj = path2.length; j < jj; j++) {\n var pj = path2[j];\n if (pj[0] == \"M\") {\n x2 = x2m = pj[1];\n y2 = y2m = pj[2];\n } else {\n if (pj[0] == \"C\") {\n bez2 = [x2, y2].concat(pj.slice(1));\n x2 = bez2[6];\n y2 = bez2[7];\n } else {\n bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];\n x2 = x2m;\n y2 = y2m;\n }\n var intr = interHelper(bez1, bez2, justCount);\n if (justCount) {\n res += intr;\n } else {\n for (var k = 0, kk = intr.length; k < kk; k++) {\n intr[k].segment1 = i;\n intr[k].segment2 = j;\n intr[k].bez1 = bez1;\n intr[k].bez2 = bez2;\n }\n res = res.concat(intr);\n }\n }\n }\n }\n }\n return res;\n }\n /*\\\n * Raphael.isPointInsidePath\n [ method ]\n **\n * Utility method\n **\n * Returns `true` if given point is inside a given closed path.\n > Parameters\n - path (string) path string\n - x (number) x of the point\n - y (number) y of the point\n = (boolean) true, if point is inside the path\n \\*/\n R.isPointInsidePath = function (path, x, y) {\n var bbox = R.pathBBox(path);\n return R.isPointInsideBBox(bbox, x, y) &&\n interPathHelper(path, [[\"M\", x, y], [\"H\", bbox.x2 + 10]], 1) % 2 == 1;\n };\n R._removedFactory = function (methodname) {\n return function () {\n eve(\"raphael.log\", null, \"Rapha\\xebl: you are calling to method \\u201c\" + methodname + \"\\u201d of removed object\", methodname);\n };\n };\n /*\\\n * Raphael.pathBBox\n [ method ]\n **\n * Utility method\n **\n * Return bounding box of a given path\n > Parameters\n - path (string) path string\n = (object) bounding box\n o {\n o x: (number) x coordinate of the left top point of the box\n o y: (number) y coordinate of the left top point of the box\n o x2: (number) x coordinate of the right bottom point of the box\n o y2: (number) y coordinate of the right bottom point of the box\n o width: (number) width of the box\n o height: (number) height of the box\n o cx: (number) x coordinate of the center of the box\n o cy: (number) y coordinate of the center of the box\n o }\n \\*/\n var pathDimensions = R.pathBBox = function (path) {\n var pth = paths(path);\n if (pth.bbox) {\n return clone(pth.bbox);\n }\n if (!path) {\n return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};\n }\n path = path2curve(path);\n var x = 0,\n y = 0,\n X = [],\n Y = [],\n p;\n for (var i = 0, ii = path.length; i < ii;
57590 i++) {\n p = path[i];\n if (p[0] == \"M\") {\n x = p[1];\n y = p[2];\n X.push(x);\n Y.push(y);\n } else {\n var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n X = X[concat](dim.min.x, dim.max.x);\n Y = Y[concat](dim.min.y, dim.max.y);\n x = p[5];\n y = p[6];\n }\n }\n var xmin = mmin[apply](0, X),\n ymin = mmin[apply](0, Y),\n xmax = mmax[apply](0, X),\n ymax = mmax[apply](0, Y),\n width = xmax - xmin,\n height = ymax - ymin,\n bb = {\n x: xmin,\n y: ymin,\n x2: xmax,\n y2: ymax,\n width: width,\n height: height,\n cx: xmin + width / 2,\n cy: ymin + height / 2\n };\n pth.bbox = clone(bb);\n return bb;\n },\n pathClone = function (pathArray) {\n var res = clone(pathArray);\n res.toString = R._path2string;\n return res;\n },\n pathToRelative = R._pathToRelative = function (pathArray) {\n var pth = paths(pathArray);\n if (pth.rel) {\n return pathClone(pth.rel);\n }\n if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n pathArray = R.parsePathString(pathArray);\n }\n var res = [],\n x = 0,\n y = 0,\n mx = 0,\n my = 0,\n start = 0;\n if (pathArray[0][0] == \"M\") {\n x = pathArray[0][1];\n y = pathArray[0][2];\n mx = x;\n my = y;\n start++;\n res.push([\"M\", x, y]);\n }\n for (var i = start, ii = pathArray.length; i < ii; i++) {\n var r = res[i] = [],\n pa = pathArray[i];\n if (pa[0] != lowerCase.call(pa[0])) {\n r[0] = lowerCase.call(pa[0]);\n switch (r[0]) {\n case \"a\":\n r[1] = pa[1];\n r[2] = pa[2];\n r[3] = pa[3];\n r[4] = pa[4];\n r[5] = pa[5];\n r[6] = +(pa[6] - x).toFixed(3);\n r[7] = +(pa[7] - y).toFixed(3);\n break;\n case \"v\":\n r[1] = +(pa[1] - y).toFixed(3);\n break;\n case \"m\":\n mx = pa[1];\n my = pa[2];\n default:\n for (var j = 1, jj = pa.length; j < jj; j++) {\n r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);\n }\n }\n } else {\n r = res[i] = [];\n if (pa[0] == \"m\") {\n mx = pa[1] + x;\n my = pa[2] + y;\n }\n for (var k = 0, kk = pa.length; k < kk; k++) {\n res[i][k] = pa[k];\n }\n }\n var len = res[i].length;\n switch (res[i][0]) {\n case \"z\":\n x = mx;\n y = my;\n break;\n case \"h\":\n x += +res[i][len - 1];\n break;\n case \"v\":\n y += +res[i][len - 1];\n break;\n default:\n x += +res[i][len - 2];\n y += +res[i][len - 1];\n }\n }\n res.toString = R._path2string;\n pth.rel = pathClone(res);\n return res;\n },\n pathToAbsolute = R._pathToAbsolute = function (pathArray) {\n var pth = paths(pathArray);\n if (pth.abs) {\n return pathClone(pth.abs);\n }\n if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption\n pathArray = R.parsePathString(pathArray);\n }\n if (!pathArray || !pathArray.length) {\n return [[\"M\", 0, 0]];\n }\n var res = [],\n x = 0,\n y = 0,\n mx = 0,\n my = 0,\n start = 0;\n if (pathArray[0][0] == \"M\") {\n x = +pathArray[0][1];\n y = +pathArray[0][2];\n mx = x;\n my = y;\n start++;\n res[0] = [\"M\", x, y];\n }\n var crz = pathArray.length == 3 && pathArray[0][0] == \"M\" && pathArray[1][0].toUpperCase() == \"R\" && pathArray[2][0].toUpperCase() == \"Z\";\n for (var r, pa, i = start, ii = pathArray.length; i < ii;
57590 i++) {\n res.push(r = []);\n pa = pathArray[i];\n if (pa[0] != upperCase.call(pa[0])) {\n r[0] = upperCase.call(pa[0]);\n switch (r[0]) {\n case \"A\":\n r[1] = pa[1];\n r[2] = pa[2];\n r[3] = pa[3];\n r[4] = pa[4];\n r[5] = pa[5];\n r[6] = +(pa[6] + x);\n r[7] = +(pa[7] + y);\n break;\n case \"V\":\n r[1] = +pa[1] + y;\n break;\n case \"H\":\n r[1] = +pa[1] + x;\n break;\n case \"R\":\n var dots = [x, y][concat](pa.slice(1));\n for (var j = 2, jj = dots.length; j < jj; j++) {\n dots[j] = +dots[j] + x;\n dots[++j] = +dots[j] + y;\n }\n res.pop();\n res = res[concat](catmullRom2bezier(dots, crz));\n break;\n case \"M\":\n mx = +pa[1] + x;\n my = +pa[2] + y;\n default:\n for (j = 1, jj = pa.length; j < jj; j++) {\n r[j] = +pa[j] + ((j % 2) ? x : y);\n }\n }\n } else if (pa[0] == \"R\") {\n dots = [x, y][concat](pa.slice(1));\n res.pop();\n res = res[concat](catmullRom2bezier(dots, crz));\n r = [\"R\"][concat](pa.slice(-2));\n } else {\n for (var k = 0, kk = pa.length; k < kk; k++) {\n r[k] = pa[k];\n }\n }\n switch (r[0]) {\n case \"Z\":\n x = mx;\n y = my;\n break;\n case \"H\":\n x = r[1];\n break;\n case \"V\":\n y = r[1];\n break;\n case \"M\":\n mx = r[r.length - 2];\n my = r[r.length - 1];\n default:\n x = r[r.length - 2];\n y = r[r.length - 1];\n }\n }\n res.toString = R._path2string;\n pth.abs = pathClone(res);\n return res;\n },\n l2c = function (x1, y1, x2, y2) {\n return [x1, y1, x2, y2, x2, y2];\n },\n q2c = function (x1, y1, ax, ay, x2, y2) {\n var _13 = 1 / 3,\n _23 = 2 / 3;\n return [\n _13 * x1 + _23 * ax,\n _13 * y1 + _23 * ay,\n _13 * x2 + _23 * ax,\n _13 * y2 + _23 * ay,\n x2,\n y2\n ];\n },\n a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {\n // for more information of where this math came from visit:\n // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes\n var _120 = PI * 120 / 180,\n rad = PI / 180 * (+angle || 0),\n res = [],\n xy,\n rotate = cacher(function (x, y, rad) {\n var X = x * math.cos(rad) - y * math.sin(rad),\n Y = x * math.sin(rad) + y * math.cos(rad);\n return {x: X, y: Y};\n });\n if (!recursive) {\n xy = rotate(x1, y1, -rad);\n x1 = xy.x;\n y1 = xy.y;\n xy = rotate(x2, y2, -rad);\n x2 = xy.x;\n y2 = xy.y;\n var cos = math.cos(PI / 180 * angle),\n sin = math.sin(PI / 180 * angle),\n x = (x1 - x2) / 2,\n y = (y1 - y2) / 2;\n var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);\n if (h > 1) {\n h = math.sqrt(h);\n rx = h * rx;\n ry = h * ry;\n }\n var rx2 = rx * rx,\n ry2 = ry * ry,\n k = (large_arc_flag == sweep_flag ? -1 : 1) *\n math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),\
57590n cx = k * rx * y / ry + (x1 + x2) / 2,\n cy = k * -ry * x / rx + (y1 + y2) / 2,\n f1 = math.asin(((y1 - cy) / ry).toFixed(9)),\n f2 = math.asin(((y2 - cy) / ry).toFixed(9));\n\n f1 = x1 < cx ? PI - f1 : f1;\n f2 = x2 < cx ? PI - f2 : f2;\n f1 < 0 && (f1 = PI * 2 + f1);\n f2 < 0 && (f2 = PI * 2 + f2);\n if (sweep_flag && f1 > f2) {\n f1 = f1 - PI * 2;\n }\n if (!sweep_flag && f2 > f1) {\n f2 = f2 - PI * 2;\n }\n } else {\n f1 = recursive[0];\n f2 = recursive[1];\n cx = recursive[2];\n cy = recursive[3];\n }\n var df = f2 - f1;\n if (abs(df) > _120) {\n var f2old = f2,\n x2old = x2,\n y2old = y2;\n f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);\n x2 = cx + rx * math.cos(f2);\n y2 = cy + ry * math.sin(f2);\n res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);\n }\n df = f2 - f1;\n var c1 = math.cos(f1),\n s1 = math.sin(f1),\n c2 = math.cos(f2),\n s2 = math.sin(f2),\n t = math.tan(df / 4),\n hx = 4 / 3 * rx * t,\n hy = 4 / 3 * ry * t,\n m1 = [x1, y1],\n m2 = [x1 + hx * s1, y1 - hy * c1],\n m3 = [x2 + hx * s2, y2 - hy * c2],\n m4 = [x2, y2];\n m2[0] = 2 * m1[0] - m2[0];\n m2[1] = 2 * m1[1] - m2[1];\n if (recursive) {\n return [m2, m3, m4][concat](res);\n } else {\n res = [m2, m3, m4][concat](res).join()[split](\",\");\n var newres = [];\n for (var i = 0, ii = res.length; i < ii; i++) {\n newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;\n }\n return newres;\n }\n },\n findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {\n var t1 = 1 - t;\n return {\n x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,\n y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y\n };\n },\n curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {\n var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),\n b = 2 * (c1x - p1x) - 2 * (c2x - c1x),\n c = p1x - c1x,\n t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,\n t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,\n y = [p1y, p2y],\n x = [p1x, p2x],\n dot;\n abs(t1) > \"1e12\" && (t1 = .5);\n abs(t2) > \"1e12\" && (t2 = .5);\n if (t1 > 0 && t1 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n x.push(dot.x);\n y.push(dot.y);\n }\n if (t2 > 0 && t2 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n x.push(dot.x);\n y.push(dot.y);\n }\n a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);\n b = 2 * (c1y - p1y) - 2 * (c2y - c1y);\n c = p1y - c1y;\n t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;\n t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;\n abs(t1) > \"1e12\" && (t1 = .5);\n abs(t2) > \"1e12\" && (t2 = .5);\n if (t1 > 0 && t1 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);\n x.push(dot.x);\n y.push(dot.y);\n }\n if (t2 > 0 && t2 < 1) {\n dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);\n x.push(dot.x);\n y.push(dot.y);\n }\n return {\n min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},\n max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}\n };\n }),\n path2curve = R._path2curve = cacher(function (path, path2) {\n var pth = !path2 && paths(path);\n if (!path2 && pth.curve) {\n return pathClone(pth.curve);\n }\n var p = pathToAbsolute(path),\n p2 = path2 && pathToAbsolute(path2),\n attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},\n processPath = function (path, d, pcom) {\n var nx, ny, tq = {T:1, Q:1};\n if (!path) {\n return [\"C\", d.x, d.y, d.x, d.y, d.x, d.y];\n }\n !(path[0] in tq) && (d.qx = d.qy = null);\n switch (path[0]) {\n case \"M\":\n d.X = path[1];\n d.Y = path[2];\n break;\n case \"A\":\n path = [\"C\"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));\n break;\n case \"S\":\n if (pcom == \"C\" || pcom == \"S\") { // In \"S\" case we have to take into account, if the previous command is C/S.\n nx = d.x * 2 - d.bx; // And reflect the previous\n ny = d.y * 2 - d.by; // command's control point relative to the current point.\n }\n else { // or some else or nothing\n nx = d.x;\n ny = d.y;\n }\n path = [\"C\", nx, ny][concat](path.slice(1));\n break;\n case \"T\":\n if (pcom == \"Q\" || pcom == \"T\") { // In \"T\" case we have to take into account, if the previous command is Q/T.\n d.qx = d.x * 2 - d.qx; // And make a reflection similar\n d.qy = d.y * 2 - d.qy; // to case \"S\".\n }\n else { // or something else or nothing\n d.qx = d.x;\n d.qy = d.y;\n }\n path = [\"C\"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));\n break;\n case \"Q\":\n d.qx = path[1];\n d.qy = path[2];\n path = [\"C\"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));\n break;\n case \"L\":\n path = [\"C\"][concat](l2c(d.x, d.y, path[1], path[2]));\n break;\n case \"H\":\n path = [\"C\"][concat](l2c(d.x, d.y, path[1], d.y));\n break;\n case \"V\":\n path = [\"C\"][concat](l2c(d.x, d.y, d.x, path[1]));\n break;\n case \"Z\":\n path = [\"C\"][concat](l2c(d.x, d.y, d.X, d.Y));\n break;\n }\n return path;\n },\n fixArc = function (pp, i) {\n if (pp[i].length > 7) {\n pp[i].shift();\n var pi = pp[i];\n while (pi.length) {\n pcoms1[i]=\"A\"; // if created multiple C:s, their original seg is saved\n p2 && (pcoms2[i]=\"A\"); // the same as above\n pp.splice(i++, 0, [\"C\"][concat](pi.splice(0, 6)));\n }\n pp.splice(i, 1);\n ii = mmax(p.length, p2 && p2.length || 0);\n }\n },\n fixM = function (path1, path2, a1, a2, i) {\n if (path1 && path2 && path1[i][0] == \"M\" && path2[i][0] != \"M\") {\n path2.splice(i, 0, [\"M\", a2.x, a2.y]);\n a1.bx = 0;\n a1.by = 0;\n a1.x = path1[i][1];\n a1.y = path1[i][2];\n ii = mmax(p.length, p2 && p2.length || 0);\n }\n },\n pcoms1 = [], // path commands of original path p\n pcoms2 = [], // path commands of original path p2\n pfirst = \"\", // temporary holder for original path command\n pcom = \"\"; // holder for previous path command of original path\n for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii;
57590 i++) {\n p[i] && (pfirst = p[i][0]); // save current path command\n\n if (pfirst != \"C\") // C is not saved yet, because it may be result of conversion\n {\n pcoms1[i] = pfirst; // Save current path command\n i && ( pcom = pcoms1[i-1]); // Get previous path command pcom\n }\n p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath\n\n if (pcoms1[i] != \"A\" && pfirst == \"C\") pcoms1[i] = \"C\"; // A is the only command\n // which may produce multiple C:s\n // so we have to make sure that C is also C in original path\n\n fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1\n\n if (p2) { // the same procedures is done to p2\n p2[i] && (pfirst = p2[i][0]);\n if (pfirst != \"C\")\n {\n pcoms2[i] = pfirst;\n i && (pcom = pcoms2[i-1]);\n }\n p2[i] = processPath(p2[i], attrs2, pcom);\n\n if (pcoms2[i]!=\"A\" && pfirst==\"C\") pcoms2[i]=\"C\";\n\n fixArc(p2, i);\n }\n fixM(p, p2, attrs, attrs2, i);\n fixM(p2, p, attrs2, attrs, i);\n var seg = p[i],\n seg2 = p2 && p2[i],\n seglen = seg.length,\n seg2len = p2 && seg2.length;\n attrs.x = seg[seglen - 2];\n attrs.y = seg[seglen - 1];\n attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;\n attrs.by = toFloat(seg[seglen - 3]) || attrs.y;\n attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);\n attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);\n attrs2.x = p2 && seg2[seg2len - 2];\n attrs2.y = p2 && seg2[seg2len - 1];\n }\n if (!p2) {\n pth.curve = pathClone(p);\n }\n return p2 ? [p, p2] : p;\n }, null, pathClone),\n parseDots = R._parseDots = cacher(function (gradient) {\n var dots = [];\n for (var i = 0, ii = gradient.length; i < ii; i++) {\n var dot = {},\n par = gradient[i].match(/^([^:]*):?([\\d\\.]*)/);\n dot.color = R.getRGB(par[1]);\n if (dot.color.error) {\n return null;\n }\n dot.opacity = dot.color.opacity;\n dot.color = dot.color.hex;\n par[2] && (dot.offset = par[2] + \"%\");\n dots.push(dot);\n }\n for (i = 1, ii = dots.length - 1; i < ii; i++) {\n if (!dots[i].offset) {\n var start = toFloat(dots[i - 1].offset || 0),\n end = 0;\n for (var j = i + 1; j < ii; j++) {\n if (dots[j].offset) {\n end = dots[j].offset;\n break;\n }\n }\n if (!end) {\n end = 100;\n j = ii;\n }\n end = toFloat(end);\n var d = (end - start) / (j - i + 1);\n for (; i < j; i++) {\n start += d;\n dots[i].offset = start + \"%\";\n }\n }\n }\n return dots;\n }),\n tear = R._tear = function (el, paper) {\n el == paper.top && (paper.top = el.prev);\n el == paper.bottom && (paper.bottom = el.next);\n el.next && (el.next.prev = el.prev);\n el.prev && (el.prev.next = el.next);\n },\n tofront = R._tofront = function (el, paper) {\n if (paper.top === el) {\n return;\n }\n tear(el, paper);\n el.next = null;\n el.prev = paper.top;\n paper.top.next = el;\n paper.top = el;\n },\n toback = R._toback = function (el, paper) {\n if (paper.bottom === el) {\n return;\n }\n tear(el, paper);\n el.next = paper.bottom;\n el.prev = null;\n paper.bottom.prev = el;\n paper.bottom = el;\n },\n insertafter = R._insertafter = function (el, el2, paper) {\n tear(el, paper);\n el2 == paper.top && (paper.top = el);\n el2.next && (el2.next.prev = el);\n el.next = el2.next;\n el.prev = el2;\n el2.next = el;\n },\n insertbefore = R._insertbefore = function (el, el2, paper) {\n tear(el, paper);\n el2 == paper.bottom && (paper.bottom = el);\n el2.prev && (el2.prev.next = el);\n el.prev = el2.prev;\n el2.prev = el;\n el.next = el2;\n },\n /*\\\n * Raphael.toMatrix\n [ method ]\n **\n * Utility method\n **\n * Returns matrix of transformations applied to a given path\n > Parameters\n - path (string) path string\n - transform (string|array) transformation string\n = (object) @Matr
57590ix\n \\*/\n toMatrix = R.toMatrix = function (path, transform) {\n var bb = pathDimensions(path),\n el = {\n _: {\n transform: E\n },\n getBBox: function () {\n return bb;\n }\n };\n extractTransform(el, transform);\n return el.matrix;\n },\n /*\\\n * Raphael.transformPath\n [ method ]\n **\n * Utility method\n **\n * Returns path transformed by a given transformation\n > Parameters\n - path (string) path string\n - transform (string|array) transformation string\n = (string) path\n \\*/\n transformPath = R.transformPath = function (path, transform) {\n return mapPath(path, toMatrix(path, transform));\n },\n extractTransform = R._extractTransform = function (el, tstr) {\n if (tstr == null) {\n return el._.transform;\n }\n tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, el._.transform || E);\n var tdata = R.parseTransformString(tstr),\n deg = 0,\n dx = 0,\n dy = 0,\n sx = 1,\n sy = 1,\n _ = el._,\n m = new Matrix;\n _.transform = tdata || [];\n if (tdata) {\n for (var i = 0, ii = tdata.length; i < ii; i++) {\n var t = tdata[i],\n tlen = t.length,\n command = Str(t[0]).toLowerCase(),\n absolute = t[0] != command,\n inver = absolute ? m.invert() : 0,\n x1,\n y1,\n x2,\n y2,\n bb;\n if (command == \"t\" && tlen == 3) {\n if (absolute) {\n x1 = inver.x(0, 0);\n y1 = inver.y(0, 0);\n x2 = inver.x(t[1], t[2]);\n y2 = inver.y(t[1], t[2]);\n m.translate(x2 - x1, y2 - y1);\n } else {\n m.translate(t[1], t[2]);\n }\n } else if (command == \"r\") {\n if (tlen == 2) {\n bb = bb || el.getBBox(1);\n m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n deg += t[1];\n } else if (tlen == 4) {\n if (absolute) {\n x2 = inver.x(t[2], t[3]);\n y2 = inver.y(t[2], t[3]);\n m.rotate(t[1], x2, y2);\n } else {\n m.rotate(t[1], t[2], t[3]);\n }\n deg += t[1];\n }\n } else if (command == \"s\") {\n if (tlen == 2 || tlen == 3) {\n bb = bb || el.getBBox(1);\n m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);\n sx *= t[1];\n sy *= t[tlen - 1];\n } else if (tlen == 5) {\n if (absolute) {\n x2 = inver.x(t[3], t[4]);\n y2 = inver.y(t[3], t[4]);\n m.scale(t[1], t[2], x2, y2);\n } else {\n m.scale(t[1], t[2], t[3], t[4]);\n }\n sx *= t[1];\n sy *= t[2];\n }\n } else if (command == \"m\" && tlen == 7) {\n m.add(t[1], t[2], t[3], t[4], t[5], t[6]);\n }\n _.dirtyT = 1;\n el.matrix = m;\n }\n }\n\n /*\\\n * Element.matrix\n [ property (object) ]\n **\n * Keeps @Matrix object, which represents element transformation\n \\*/\n el.matrix = m;\n\n _.sx = sx;\n _.sy = sy;\n _.deg = deg;\n _.dx = dx = m.e;\n _.dy = dy = m.f;\n\n if (sx == 1 && sy == 1 && !deg && _.bbox) {\n _.bbox.x += +dx;\n _.bbox.y += +dy;\n } else {\n _.dirtyT = 1;\n }\n },\n getEmpty = function (item) {\n var l = item[0];\n switch (l.toLowerCase()) {\n case \"t\": return [l, 0, 0];\n case \"m\": return [l, 1, 0, 0, 1, 0, 0];\n case \"r\": if (item.length == 4) {\n return [l, 0, item[2], item[3]];\n } else {\n return [l, 0];\n }\n case \"s\": if (item.length == 5) {\n return [l, 1, 1, item[3], item[4]];\n } else if (item.length == 3) {\n return [l, 1, 1];\n } else {\n return [l, 1];\n }\n }\n },\n equaliseTransform = R._equaliseTransform = function (t1, t2) {\n t2 = Str(t2).replace(/\\.{3}|\\u2026/g, t1);\n t1 = R.parseTransformString(t1) || [];\n t2 = R.parseTransformString(t2) || [];\n var maxlength = mmax(t1.length, t2.length),\n from = [],\n to = [],\n i = 0, j, jj,\n tt1, tt2;\n for (; i < maxlength;
57590 i++) {\n tt1 = t1[i] || getEmpty(t2[i]);\n tt2 = t2[i] || getEmpty(tt1);\n if ((tt1[0] != tt2[0]) ||\n (tt1[0].toLowerCase() == \"r\" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||\n (tt1[0].toLowerCase() == \"s\" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))\n ) {\n return;\n }\n from[i] = [];\n to[i] = [];\n for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {\n j in tt1 && (from[i][j] = tt1[j]);\n j in tt2 && (to[i][j] = tt2[j]);\n }\n }\n return {\n from: from,\n to: to\n };\n };\n R._getContainer = function (x, y, w, h) {\n var container;\n container = h == null && !R.is(x, \"object\") ? g.doc.getElementById(x) : x;\n if (container == null) {\n return;\n }\n if (container.tagName) {\n if (y == null) {\n return {\n container: container,\n width: container.style.pixelWidth || container.offsetWidth,\n height: container.style.pixelHeight || container.offsetHeight\n };\n } else {\n return {\n container: container,\n width: y,\n height: w\n };\n }\n }\n return {\n container: 1,\n x: x,\n y: y,\n width: w,\n height: h\n };\n };\n /*\\\n * Raphael.pathToRelative\n [ method ]\n **\n * Utility method\n **\n * Converts path to relative form\n > Parameters\n - pathString (string|array) path string or array of segments\n = (array) array of segments.\n \\*/\n R.pathToRelative = pathToRelative;\n R._engine = {};\n /*\\\n * Raphael.path2curve\n [ method ]\n **\n * Utility method\n **\n * Converts path to a new path where all segments are cubic bezier curves.\n > Parameters\n - pathString (string|array) path string or array of segments\n = (array) array of segments.\n \\*/\n R.path2curve = path2curve;\n /*\\\n * Raphael.matrix\n [ method ]\n **\n * Utility method\n **\n * Returns matrix based on given parameters.\n > Parameters\n - a (number)\n - b (number)\n - c (number)\n - d (number)\n - e (number)\n - f (number)\n = (object) @Matrix\n \\*/\n R.matrix = function (a, b, c, d, e, f) {\n return new Matrix(a, b, c, d, e, f);\n };\n function Matrix(a, b, c, d, e, f) {\n if (a != null) {\n this.a = +a;\n this.b = +b;\n this.c = +c;\n this.d = +d;\n this.e = +e;\n this.f = +f;\n } else {\n this.a = 1;\n this.b = 0;\n this.c = 0;\n this.d = 1;\n this.e = 0;\n this.f = 0;\n }\n }\n (function (matrixproto) {\n /*\\\n * Matrix.add\n [ method ]\n **\n * Adds given matrix to existing one.\n > Parameters\n - a (number)\n - b (number)\n - c (number)\n - d (number)\n - e (number)\n - f (number)\n or\n - matrix (object) @Matrix\n \\*/\n matrixproto.add = function (a, b, c, d, e, f) {\n var out = [[], [], []],\n m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],\n matrix = [[a, c, e], [b, d, f], [0, 0, 1]],\n x, y, z, res;\n\n if (a && a instanceof Matrix) {\n matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];\n }\n\n for (x = 0; x < 3; x++) {\n for (y = 0; y < 3; y++) {\n res = 0;\n for (z = 0; z < 3; z++) {\n res += m[x][z] * matrix[z][y];\n }\n out[x][y] = res;\n }\n }\n this.a = out[0][0];\n this.b = out[1][0];\n this.c = out[0][1];\n this.d = out[1][1];\n this.e = out[0][2];\n this.f = out[1][2];\n };\n /*\\\n * Matrix.invert\n [ method ]\n **\n * Returns inverted version of the matrix\n = (object) @Matr
57590ix\n \\*/\n matrixproto.invert = function () {\n var me = this,\n x = me.a * me.d - me.b * me.c;\n return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);\n };\n /*\\\n * Matrix.clone\n [ method ]\n **\n * Returns copy of the matrix\n = (object) @Matrix\n \\*/\n matrixproto.clone = function () {\n return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);\n };\n /*\\\n * Matrix.translate\n [ method ]\n **\n * Translate the matrix\n > Parameters\n - x (number)\n - y (number)\n \\*/\n matrixproto.translate = function (x, y) {\n this.add(1, 0, 0, 1, x, y);\n };\n /*\\\n * Matrix.scale\n [ method ]\n **\n * Scales the matrix\n > Parameters\n - x (number)\n - y (number) #optional\n - cx (number) #optional\n - cy (number) #optional\n \\*/\n matrixproto.scale = function (x, y, cx, cy) {\n y == null && (y = x);\n (cx || cy) && this.add(1, 0, 0, 1, cx, cy);\n this.add(x, 0, 0, y, 0, 0);\n (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);\n };\n /*\\\n * Matrix.rotate\n [ method ]\n **\n * Rotates the matrix\n > Parameters\n - a (number)\n - x (number)\n - y (number)\n \\*/\n matrixproto.rotate = function (a, x, y) {\n a = R.rad(a);\n x = x || 0;\n y = y || 0;\n var cos = +math.cos(a).toFixed(9),\n sin = +math.sin(a).toFixed(9);\n this.add(cos, sin, -sin, cos, x, y);\n this.add(1, 0, 0, 1, -x, -y);\n };\n /*\\\n * Matrix.x\n [ method ]\n **\n * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y\n > Parameters\n - x (number)\n - y (number)\n = (number) x\n \\*/\n matrixproto.x = function (x, y) {\n return x * this.a + y * this.c + this.e;\n };\n /*\\\n * Matrix.y\n [ method ]\n **\n * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x\n > Parameters\n - x (number)\n - y (number)\n = (number) y\n \\*/\n matrixproto.y = function (x, y) {\n return x * this.b + y * this.d + this.f;\n };\n matrixproto.get = function (i) {\n return +this[Str.fromCharCode(97 + i)].toFixed(4);\n };\n matrixproto.toString = function () {\n return R.svg ?\n \"matrix(\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + \")\" :\n [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();\n };\n matrixproto.toFilter = function () {\n return \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + this.get(0) +\n \", M12=\" + this.get(2) + \", M21=\" + this.get(1) + \", M22=\" + this.get(3) +\n \", Dx=\" + this.get(4) + \", Dy=\" + this.get(5) + \", sizingmethod='auto expand')\";\n };\n matrixproto.offset = function () {\n return [this.e.toFixed(4), this.f.toFixed(4)];\n };\n function norm(a) {\n return a[0] * a[0] + a[1] * a[1];\n }\n function normalize(a) {\n var mag = math.sqrt(norm(a));\n a[0] && (a[0] /= mag);\n a[1] && (a[1] /= mag);\n }\n /*\\\n * Matrix.split\n [ method ]\n **\n * Splits matrix into primitive transformations\n = (object) in format:\n o dx (number) translation by x\n o dy (number) translation by y\n o scalex (number) scale by x\n o scaley (number) scale by y\n o shear (number) shear\n o rotate (number) rotation in deg\n o isSimple (boolean) could it be represented via simple transformations\n \\*/\n matrixproto.split = function () {\n var out = {};\n // translation\n out.dx = this.e;\n out.dy = this.f;\n\n // scale and shear\n var row = [[this.a, this.c], [this.b, this.d]];\n out.scalex = math.sqrt(norm(row[0]));\n normalize(row[0]);\n\n out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];\n row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];\n\n out.scaley = math.sqrt(norm(row[1]));\n normalize(row[1]);\n out.shear /= out.scaley;\n\n // rotation\n var sin = -row[0][1],\n cos = row[1][1];\n if (cos < 0) {\n out.rotate = R.deg(math.acos(cos));\n if (sin < 0) {\n out.rotate = 360 - out.rotate;\n }\n } else {\n out.rotate = R.deg(math.asin(sin));\n }\n\n out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);\n out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;\n out.noRotation = !+out.shear.toFixed(9) && !out.rotate;\n return out;\n };\n /*\\\n * Matrix.toTransformString\n [ method ]\n **\n * Return transform string that represents given matrix\n = (string) transform string\n \\*/\n matrixproto.toTransformString = function (shorter) {\n var s = shorter || this[split]();\n if (s.isSimple) {\n s.scalex = +s.scalex.toFixed(4);\n s.scaley = +s.scaley.toFixed(4);\n s.rotate = +s.rotate.toFixed(4);\n return (s.dx || s.dy ? \"t\" + [s.dx, s.dy] : E) +\n (s.scalex != 1 || s.scaley != 1 ? \"s\" + [s.scalex, s.scaley, 0, 0] : E) +\n (s.rotate ? \"r\" + [s.rotate, 0, 0] : E);\n } else {\n return \"m\" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];\n }\n };\n })(Matrix.prototype);\n\n var preventDefault = function () {\n this.returnValue = false;\n },\n preventTouch = function () {\n return this.originalEvent.preventDefault();\n },\n stopPropagation = function () {\n this.cancelBubble = true;\n },\n stopTouch = function () {\n return this.originalEvent.stopPropagation();\n },\n getEventPosition = function (e) {\n var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n\n return {\n x: e.clientX + scrollX,\n y: e.clientY + scrollY\n };\n },\n addEvent = (function () {\n if (g.doc.addEventListener) {\n return function (obj, type, fn, element) {\n var f = function (e) {\n var pos = getEventPosition(e);
57590\n return fn.call(element, e, pos.x, pos.y);\n };\n obj.addEventListener(type, f, false);\n\n if (supportsTouch && touchMap[type]) {\n var _f = function (e) {\n var pos = getEventPosition(e),\n olde = e;\n\n for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {\n if (e.targetTouches[i].target == obj) {\n e = e.targetTouches[i];\n e.originalEvent = olde;\n e.preventDefault = preventTouch;\n e.stopPropagation = stopTouch;\n break;\n }\n }\n\n return fn.call(element, e, pos.x, pos.y);\n };\n obj.addEventListener(touchMap[type], _f, false);\n }\n\n return function () {\n obj.removeEventListener(type, f, false);\n\n if (supportsTouch && touchMap[type])\n obj.removeEventListener(touchMap[type], _f, false);\n\n return true;\n };\n };\n } else if (g.doc.attachEvent) {\n return function (obj, type, fn, element) {\n var f = function (e) {\n e = e || g.win.event;\n var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n x = e.clientX + scrollX,\n y = e.clientY + scrollY;\n e.preventDefault = e.preventDefault || preventDefault;\n e.stopPropagation = e.stopPropagation || stopPropagation;\n return fn.call(element, e, x, y);\n };\n obj.attachEvent(\"on\" + type, f);\n var detacher = function () {\n obj.detachEvent(\"on\" + type, f);\n return true;\n };\n return detacher;\n };\n }\n })(),\n drag = [],\n dragMove = function (e) {\n var x = e.clientX,\n y = e.clientY,\n scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,\n dragi,\n j = drag.length;\n while (j--) {\n dragi = drag[j];\n if (supportsTouch && e.touches) {\n var i = e.touches.length,\n touch;\n while (i--) {\n touch = e.touches[i];\n if (touch.identifier == dragi.el._drag.id) {\n x = touch.clientX;\n y = touch.clientY;\n (e.originalEvent ? e.originalEvent : e).preventDefault();\n break;\n }\n }\n } else {\n e.preventDefault();\n }\n var node = dragi.el.node,\n o,\n next = node.nextSibling,\n parent = node.parentNode,\n display = node.style.display;\n g.win.opera && parent.removeChild(node);\n node.style.display = \"none\";\n o = dragi.el.paper.getElementByPoint(x, y);\n node.style.display = display;\n g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));\n o && eve(\"raphael.drag.over.\" + dragi.el.id, dragi.el, o);\n x += scrollX;\n y += scrollY;\n eve(\"raphael.drag.move.\" + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);\n }\n },\n dragUp = function (e) {\n R.unmousemove(dragMove).unmouseup(dragUp);\n var i = drag.length,\n dragi;\n while (i--) {\n dragi = drag[i];\n dragi.el._drag = {};\n eve(\"raphael.drag.end.\" + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);\n }\n drag = [];\n },\n /*\\\n * Raphael.el\n [ property (object) ]\n **\n * You can add your own method to elements. This is useful when you want to hack default functionality or\n * want to wrap some common transformation or attributes in one method. In difference to canvas methods,\n * you can redefine element method at any time. Expending element methods wouldnât affect set.\n > Usage\n | Raphael.el.red = function () {\n | this.attr({fill: \"#f00\"});\n | };\n | // then use it\n | paper.circle(100, 100, 20).red();\n \\*/\n elproto = R.el = {};\n /*\\\n * Element.click\n [ method ]\n **\n * Adds event handler for click for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unclick\n [ method ]\n **\n * Removes event handler for click for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.dblclick\n [ method ]\n **\n * Adds event handler for double click for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.undblclick\n [ method ]\n **\n * Removes event handler for double click for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mousedown\n [ method ]\n **\n * Adds event handler for mousedown for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmousedown\n [ method ]\n **\n * Removes event handler for mousedown for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mousemove\n [ method ]\n **\n * Adds event handler for mousemove for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmousemove\n [ method ]\n **\n * Removes event handler for mousemove for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseout\n [ method ]\n **\n * Adds event handler for mouseout for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseout\n [ method ]\n **\n * Removes event handler for mouseout for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseover\n [ method ]\n **\n * Adds event handler for mouseover for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseover\n [ method ]\n **\n * Removes event handler for mouseover for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.mouseup\n [ method ]\n **\n * Adds event handler for mouseup for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.unmouseup\n [ method ]\n **\n * Removes event handler for mouseup for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchstart\n [ method ]\n **\n * Adds event handler for touchstart for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchstart\n [ method ]\n **\n * Removes event handler for touchstart for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchmove\n [ method ]\n **\n * Adds event handler for touchmove for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchmove\n [ method ]\n **\n * Removes event handler for touchmove for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchend\n [ method ]\n **\n * Adds event handler for touchend for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchend\n [ method ]\n **\n * Removes event handler for touchend for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n\n /*\\\n * Element.touchcancel\n [ method ]\n **\n * Adds event handler for touchcancel for the element.\n > Parameters\n - handler (function) handler for the event\n = (object) @Element\n \\*/\n /*\\\n * Element.untouchcancel\n [ method ]\n **\n * Removes event handler for touchcancel for the element.\n > Parameters\n - handler (function) #optional handler for the event\n = (object) @Element\n \\*/\n for (var i = events.length; i--;) {\n (function (eventName) {\n R[eventName] = elproto[eventName] = function (fn, scope) {\n if (R.is(fn, \"function\")) {\n this.events = this.events || [];\n this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});\n }\n return this;\n };\n R[\"un\" + eventName] = elproto[\"un\" + eventName] = function (fn) {\n var events = this.events || [],\n l = events.length;\n while (l--){\n if (events[l].name == eventName && (R.is(fn, \"undefined\") || events[l].f == fn)) {\n events[l].unbind();\n events.splice(l, 1);\n !events.length && delete this.events;\n }\n }\n return this;\n };\n })(events[i]);\n }\n\n /*\\\n * Element.data\n [ method ]\n **\n * Adds or retrieves given value associated with given key.\n **\n * See also @Element.removeData\n > Parameters\n - key (string) key to store data\n - value (any) #optional value to store\n = (object) @Element\n * or, if value is not specified:\n = (any) value\n * or, if key and value are not specified:\n = (object) Key/value pairs for all the data associated with the element.\n >
57590 Usage\n | for (var i = 0, i < 5, i++) {\n | paper.circle(10 + 15 * i, 10, 10)\n | .attr({fill: \"#000\"})\n | .data(\"i\", i)\n | .click(function () {\n | alert(this.data(\"i\"));\n | });\n | }\n \\*/\n elproto.data = function (key, value) {\n var data = eldata[this.id] = eldata[this.id] || {};\n if (arguments.length == 0) {\n return data;\n }\n if (arguments.length == 1) {\n if (R.is(key, \"object\")) {\n for (var i in key) if (key[has](i)) {\n this.data(i, key[i]);\n }\n return this;\n }\n eve(\"raphael.data.get.\" + this.id, this, data[key], key);\n return data[key];\n }\n data[key] = value;\n eve(\"raphael.data.set.\" + this.id, this, value, key);\n return this;\n };\n /*\\\n * Element.removeData\n [ method ]\n **\n * Removes value associated with an element by given key.\n * If key is not provided, removes all the data of the element.\n > Parameters\n - key (string) #optional key\n = (object) @Element\n \\*/\n elproto.removeData = function (key) {\n if (key == null) {\n delete eldata[this.id];\n } else {\n eldata[this.id] && delete eldata[this.id][key];\n }\n return this;\n };\n /*\\\n * Element.getData\n [ method ]\n **\n * Retrieves the element data\n = (object) data\n \\*/\n elproto.getData = function () {\n return clone(eldata[this.id] || {});\n };\n /*\\\n * Element.hover\n [ method ]\n **\n * Adds event handlers for hover for the element.\n > Parameters\n - f_in (function) handler for hover in\n - f_out (function) handler for hover out\n - icontext (object) #optional context for hover in handler\n - ocontext (object) #optional context for hover out handler\n = (object) @Element\n \\*/\n elproto.hover = function (f_in, f_out, scope_in, scope_out) {\n return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);\n };\n /*\\\n * Element.unhover\n [ method ]\n **\n * Removes event handlers for hover for the element.\n > Parameters\n - f_in (function) handler for hover in\n - f_out (function) handler for hover out\n = (object) @Element\n \\*/\n elproto.unhover = function (f_in, f_out) {\n return this.unmouseover(f_in).unmouseout(f_out);\n };\n var draggable = [];\n /*\\\n * Element.drag\n [ method ]\n **\n * Adds event handlers for drag of the element.\n > Parameters\n - onmove (function) handler for moving\n - onstart (function) handler for drag start\n - onend (function) handler for drag end\n - mcontext (object) #optional context for moving handler\n - scontext (object) #optional context for drag start handler\n - econtext (object) #optional context for drag end handler\n * Additionally following `drag` events will be triggered: `drag.start.<id>` on start,\n * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element\n * `drag.over.<id>` will be fired as well.\n *\n * Start event and start handler will be called in specified context or in context of the element with following parameters:\n o x (number) x position of the mouse\n o y (number) y position of the mouse\n o event (object) DOM event object\n * Move event and move handler will be called in specified context or in context of the element with following parameters:\n o dx (number) shift by x from the start point\n o dy (number) shift by y from the start point\n o x (number) x position of the mouse\n o y (number) y position of the mouse\n o event (object) DOM event object\n * End event and end handler will be called in specified context or in context of the element with following parameters:\n o event (object) DOM event object\n = (object) @Element\n \\*/\n elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {\n function start(e) {\n (e.originalEvent || e).preventDefault();
57590\n var x = e.clientX,\n y = e.clientY,\n scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,\n scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;\n this._drag.id = e.identifier;\n if (supportsTouch && e.touches) {\n var i = e.touches.length, touch;\n while (i--) {\n touch = e.touches[i];\n this._drag.id = touch.identifier;\n if (touch.identifier == this._drag.id) {\n x = touch.clientX;\n y = touch.clientY;\n break;\n }\n }\n }\n this._drag.x = x + scrollX;\n this._drag.y = y + scrollY;\n !drag.length && R.mousemove(dragMove).mouseup(dragUp);\n drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});\n onstart && eve.on(\"raphael.drag.start.\" + this.id, onstart);\n onmove && eve.on(\"raphael.drag.move.\" + this.id, onmove);\n onend && eve.on(\"raphael.drag.end.\" + this.id, onend);\n eve(\"raphael.drag.start.\" + this.id, start_scope || move_scope || this, this._drag.x, this._drag.y, e);\n }\n this._drag = {};\n draggable.push({el: this, start: start});\n this.mousedown(start);\n return this;\n };\n /*\\\n * Element.onDragOver\n [ method ]\n **\n * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).\n > Parameters\n - f (function) handler for event, first argument would be the element you are dragging over\n \\*/\n elproto.onDragOver = function (f) {\n f ? eve.on(\"raphael.drag.over.\" + this.id, f) : eve.unbind(\"raphael.drag.over.\" + this.id);\n };\n /*\\\n * Element.undrag\n [ method ]\n **\n * Removes all drag event handlers from given element.\n \\*/\n elproto.undrag = function () {\n var i = draggable.length;\n while (i--) if (draggable[i].el == this) {\n this.unmousedown(draggable[i].start);\n draggable.splice(i, 1);\n eve.unbind(\"raphael.drag.*.\" + this.id);\n }\n !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);\n drag = [];\n };\n /*\\\n * Paper.circle\n [ method ]\n **\n * Draws a circle.\n **\n > Parameters\n **\n - x (number) x coordinate of the centre\n - y (number) y coordinate of the centre\n - r (number) radius\n = (object) Raphaël element object with type âcircleâ\n **\n > Usage\n | var c = paper.circle(50, 50, 40);\n \\*/\n paperproto.circle = function (x, y, r) {\n var out = R._engine.circle(this, x || 0, y || 0, r || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.rect\n [ method ]\n *\n * Draws a rectangle.\n **\n > Parameters\n **\n - x (number) x coordinate of the top left corner\n - y (number) y coordinate of the top left corner\n - width (number) width\n - height (number) height\n - r (number) #optional radius for rounded corners, default is 0\n = (object) Raphaël element object with type ârectâ\n **\n > Usage\n | // regular rectangle\n | var c = paper.rect(10, 10, 50, 50);\n | // rectangle with rounded corners\n | var c = paper.rect(40, 40, 50, 50, 10);\n \\*/\n paperproto.rect = function (x, y, w, h, r) {\n var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.ellipse\n [ method ]\n **\n * Draws an ellipse.\n **\n > Parameters\n **\n - x (number) x coordinate of the centre\n - y (number) y coordinate of the centre\n - rx (number) horizontal radius\n - ry (number) vertical radius\n = (object) Raphaël element object with type âellipseâ\n **\n > Usage\n | var c = paper.ellipse(50, 50, 40, 20);\n \\*/\n paperproto.ellipse = function (x, y, rx, ry) {\n var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.path\n [ method ]\n **\n * Creates a path element by given path data string.\n > Parameters\n - pathString (string) #optional path string in SVG format.\n * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:\n | \"M10,20L30,40\"\n * Here we can see two commands: âMâ, with arguments `(10, 20)` and âLâ with arguments `(30, 40)`. Upper case letter mean command is absolute, lower caseârelative.\n *\n # <p>Here is short list of commands available, for more details see <a href=\"http://www.w3.org/TR/SVG/paths.html#PathData\" title=\"Details of a path's data attribute's format are described
57590in the SVG specification.\">SVG path string format</a>.</p>\n # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>\n # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>\n # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>\n # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>\n # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>\n # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>\n # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>\n # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>\n # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>\n # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>\n # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>\n # <tr><td>R</td><td><a href=\"http://en.wikipedia.org/wiki/CatmullâRom_spline#Catmull.E2.80.93Rom_spline\">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>\n * * âCatmull-Rom curvetoâ is a not standard SVG command and added in 2.0 to make life easier.\n * Note: there is a special case when path consist of just three commands: âM10,10Râ¦zâ. In this case path will smoothly connects to its beginning.\n > Usage\n | var c = paper.path(\"M10 10L90 90\");\n | // draw a diagonal line:\n | // move to 10,10, line to 90,90\n * For example of path strings, check out these icons: http://raphaeljs.com/icons/\n \\*/\n paperproto.path = function (pathString) {\n pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);\n var out = R._engine.path(R.format[apply](R, arguments), this);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.image\n [ method ]\n **\n * Embeds an image into the surface.\n **\n > Parameters\n **\n - src (string) URI of the source image\n - x (number) x coordinate position\n - y (number) y coordinate position\n - width (number) width of the image\n - height (number) height of the image\n = (object) Raphaël element object with type âimageâ\n **\n > Usage\n | var c = paper.image(\"apple.png\", 10, 10, 80, 80);\n \\*/\n paperproto.image = function (src, x, y, w, h) {\n var out = R._engine.image(this, src || \"about:blank\", x || 0, y || 0, w || 0, h || 0);\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.text\n [ method ]\n **\n * Draws a text string. If you need line breaks, put â\\nâ in the string.\n **\n > Parameters\n **\n - x (number) x coordinate position\n - y (number) y coordinate position\n - text (string) The text string to draw\n = (object) Raphaël element object with type âtextâ\n **\n > Usage\n | var t = paper.text(50, 50, \"Raphaël\\nkicks\\nbutt!\");\n \\*/\n paperproto.text = function (x, y, text) {\n var out = R._engine.text(this, x || 0, y || 0, Str(text));\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Paper.set\n [ method ]\n **\n * Creates array-like object to keep and operate several elements at once.\n * Warning: it doesnât create any elements for itself in the page, it just groups existing elements.\n * Sets act as pseudo elements â all methods available to an element can be used on a set.\n = (object) array-like object that represents set of elements\n **\n > Usage\n | var st = paper.set();\n | st.push(\n | paper.circle(10, 10, 5),\n | paper.circle(30, 10, 5)\n | );\n | st.attr({fill: \"red\"}); // changes the fill of both circles\n \\*/\n paperproto.set = function (itemsArray) {\n !R.is(itemsArray, \"array\") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));\n var out = new Set(itemsArray);\n this.__set__ && this.__set__.push(out);\n out[\"paper\"] = this;\n out[\"type\"] = \"set\";\n return out;\n };\n /*\\\n * Paper.setStart\n [ method ]\n **\n * Creates @Paper.set. All elements that will be created after calling this method and before calling\n * @Paper.setFinish will be added to the set.\n **\n > Usage\n | paper.setStart();\n | paper.circle(10, 10, 5),\n | paper.circle(30, 10, 5)\n | var st = paper.setFinish();\n | st.attr({fill: \"red\"}); // changes the fill of both circles\n \\*/\n paperproto.setStart = function (set) {\n this.__set__ = set || this.set();\n };\n /*\\\n * Paper.setFinish\n [ method ]\n **\n * See @Paper.setStart. This method finishes catching and returns resulting set.\n **\n = (object) set\n \\*/\n paperproto.setFinish = function (set) {\n var out = this.__set__;\n delete this.__set__;\n return out;\n };\n /*\\\n * Paper.getSize\n [ method ]\n **\n * Obtains current paper actual size.\n **\n = (object)\n \\*/\n paperproto.getSize = function () {\n var container = this.canvas.parentNode;\n return {\n width: container.offsetWidth,\n height: container.offsetHeight\n };\n };\n /*\\\n * Paper.setSize\n [ method ]\n **\n * If you need to change dimensions of the canvas call this method\n **\n > Parameters\n **\n - width (number) new width of the canvas\n - he
57590ight (number) new height of the canvas\n \\*/\n paperproto.setSize = function (width, height) {\n return R._engine.setSize.call(this, width, height);\n };\n /*\\\n * Paper.setViewBox\n [ method ]\n **\n * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by\n * specifying new boundaries.\n **\n > Parameters\n **\n - x (number) new x position, default is `0`\n - y (number) new y position, default is `0`\n - w (number) new width of the canvas\n - h (number) new height of the canvas\n - fit (boolean) `true` if you want graphics to fit into new boundary box\n \\*/\n paperproto.setViewBox = function (x, y, w, h, fit) {\n return R._engine.setViewBox.call(this, x, y, w, h, fit);\n };\n /*\\\n * Paper.top\n [ property ]\n **\n * Points to the topmost element on the paper\n \\*/\n /*\\\n * Paper.bottom\n [ property ]\n **\n * Points to the bottom element on the paper\n \\*/\n paperproto.top = paperproto.bottom = null;\n /*\\\n * Paper.raphael\n [ property ]\n **\n * Points to the @Raphael object/function\n \\*/\n paperproto.raphael = R;\n var getOffset = function (elem) {\n var box = elem.getBoundingClientRect(),\n doc = elem.ownerDocument,\n body = doc.body,\n docElem = doc.documentElement,\n clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,\n top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,\n left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;\n return {\n y: top,\n x: left\n };\n };\n /*\\\n * Paper.getElementByPoint\n [ method ]\n **\n * Returns you topmost element under given point.\n **\n = (object) Raphaël element object\n > Parameters\n **\n - x (number) x coordinate from the top left corner of the window\n - y (number) y coordinate from the top left corner of the window\n > Usage\n | paper.getElementByPoint(mouseX, mouseY).attr({stroke: \"#f00\"});\n \\*/\n paperproto.getElementByPoint = function (x, y) {\n var paper = this,\n svg = paper.canvas,\n target = g.doc.elementFromPoint(x, y);\n if (g.win.opera && target.tagName == \"svg\") {\n var so = getOffset(svg),\n sr = svg.createSVGRect();\n sr.x = x - so.x;\n sr.y = y - so.y;\n sr.width = sr.height = 1;\n var hits = svg.getIntersectionList(sr, null);\n if (hits.length) {\n target = hits[hits.length - 1];\n }\n }\n if (!target) {\n return null;\n }\n while (target.parentNode && target != svg.parentNode && !target.raphael) {\n target = target.parentNode;\n }\n target == paper.canvas.parentNode && (target = svg);\n target = target && target.raphael ? paper.getById(target.raphaelid) : null;\n return target;\n };\n\n /*\\\n * Paper.getElementsByBBox\n [ method ]\n **\n * Returns set of elements that have an intersecting bounding box\n **\n > Parameters\n **\n - bbox (object) bbox to check with\n = (object) @Set\n \\*/\n paperproto.getElementsByBBox = function (bbox) {\n var set = this.set();\n this.forEach(function (el) {\n if (R.isBBoxIntersect(el.getBBox(), bbox)) {\n set.push(el);\n }\n });\n return set;\n };\n\n /*\\\n * Paper.getById\n [ method ]\n **\n * Returns you element by its internal ID.\n **\n > Parameters\n **\n - id (number) id\n = (object) Raphaël element object\n \\*/\n paperproto.getById = function (id) {\n var bot = this.bottom;\n while (bot) {\n if (bot.id == id) {\n return bot;\n }\n bot = bot.next;\n }\n return null;\n };\n /*\\\n * Paper.forEach\n [ method ]\n **\n * Executes given function for each element on the paper\n *\n * If callback function returns `false` it will stop loop running.\n **\n > Parameters\n **\n - callback (function) function to run\n - thisArg (object) context object for the callback\n = (object) Paper object\n > Usage\n | paper.forEach(function (el) {\n | el.attr({ stroke: \"blue\" });\n | });\n \\*/\n paperproto.forEach = function (callback, thisArg) {\n var bot = this.bottom;\n while (bot) {\n if (callback.call(thisArg, bot) === false) {\n return this;\n }\n bot = bot.next;\n }\n return this;\n };\n /*\\\n * Paper.getElementsByPoint\n [ method ]\n **\n * Returns set of elements that have common point inside\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (object) @Set\n \\*/\n paperproto.getElementsByPoint = function (x, y) {\n var set = this.set();\n this.forEach(function (el) {\n if (el.isPointInside(x, y)) {\n set.push(el);\n }\n });\n return set;\n };\n function x_y() {\n return this.x + S + this.y;\n }\n function x_y_w_h() {\n return this.x + S + this.y + S + this.width + \" \\xd7 \" + this.height;\n }\n /*\\\n * Element.isPointInside\n [ method ]\n **\n * Determine if given point is inside this elementâs shape\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (boolean) `true` if point inside the shape\n \\*/\n elproto.isPointInside = function (x, y) {\n var rp = this.realPath = getPath[this.type](this);\n if (this.attr('transform') && this.attr('transform').length) {\n rp = R.transformPath(rp, this.attr('transform'));\n }\n return R.isPointInsidePath(rp, x, y);\n };\n /*\\\n * Element.getBBox\n [ method ]\n **\n * Return bounding box for a given element\n **\n > Parameters\n **\n - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.\n = (object) Bounding box object:\n o {\n o x: (number) top left corner x\n o y: (number) top left corner y\n o x2: (number) bottom right corner x\n o y2: (number) bottom right corner y\n o width: (number) width\n o height: (number) height\n o }\n \\*/\n elproto.getBBox = function (isWithoutTransform) {\n if (this.removed) {\
57590n return {};\n }\n var _ = this._;\n if (isWithoutTransform) {\n if (_.dirty || !_.bboxwt) {\n this.realPath = getPath[this.type](this);\n _.bboxwt = pathDimensions(this.realPath);\n _.bboxwt.toString = x_y_w_h;\n _.dirty = 0;\n }\n return _.bboxwt;\n }\n if (_.dirty || _.dirtyT || !_.bbox) {\n if (_.dirty || !this.realPath) {\n _.bboxwt = 0;\n this.realPath = getPath[this.type](this);\n }\n _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));\n _.bbox.toString = x_y_w_h;\n _.dirty = _.dirtyT = 0;\n }\n return _.bbox;\n };\n /*\\\n * Element.clone\n [ method ]\n **\n = (object) clone of a given element\n **\n \\*/\n elproto.clone = function () {\n if (this.removed) {\n return null;\n }\n var out = this.paper[this.type]().attr(this.attr());\n this.__set__ && this.__set__.push(out);\n return out;\n };\n /*\\\n * Element.glow\n [ method ]\n **\n * Return set of elements that create glow-like effect around given element. See @Paper.set.\n *\n * Note: Glow is not connected to the element. If you change element attributes it wonât adjust itself.\n **\n > Parameters\n **\n - glow (object) #optional parameters object with all properties optional:\n o {\n o width (number) size of the glow, default is `10`\n o fill (boolean) will it be filled, default is `false`\n o opacity (number) opacity, default is `0.5`\n o offsetx (number) horizontal offset, default is `0`\n o offsety (number) vertical offset, default is `0`\n o color (string) glow colour, default is `black`\n o }\n = (object) @Paper.set of elements that represents glow\n \\*/\n elproto.glow = function (glow) {\n if (this.type == \"text\") {\n return null;\n }\n glow = glow || {};\n var s = {\n width: (glow.width || 10) + (+this.attr(\"stroke-width\") || 1),\n fill: glow.fill || false,\n opacity: glow.opacity == null ? .5 : glow.opacity,\n offsetx: glow.offsetx || 0,\n offsety: glow.offsety || 0,\n color: glow.color || \"#000\"\n },\n c = s.width / 2,\n r = this.paper,\n out = r.set(),\n path = this.realPath || getPath[this.type](this);\n path = this.matrix ? mapPath(path, this.matrix) : path;\n for (var i = 1; i < c + 1; i++) {\n out.push(r.path(path).attr({\n stroke: s.color,\n fill: s.fill ? s.color : \"none\",\n \"stroke-linejoin\": \"round\",\n \"stroke-linecap\": \"round\",\n \"stroke-width\": +(s.width / c * i).toFixed(3),\n opacity: +(s.opacity / c).toFixed(3)\n }));\n }\n return out.insertBefore(this).translate(s.offsetx, s.offsety);\n };\n var curveslengths = {},\n getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {\n if (length == null) {\n return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);\n } else {\n return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));\n }\n },\n getLengthFactory = function (istotal, subpath) {\n return function (path, length, onlystart) {\n path = path2curve(path);\n var x, y, p, l, sp = \"\", subpaths = {}, point,\n len = 0;\n for (var i = 0, ii = path.length; i < ii; i++) {\n p = path[i];\n if (p[0] == \"M\") {\n x = +p[1];\n y = +p[2];\n } else {\n l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);\n if (len + l > length) {\n if (subpath && !subpaths.start) {\n point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n sp += [\"C\" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];\n if (onlystart) {return sp;}\n subpaths.start = sp;\n sp = [\"M\" + point.x, point.y + \"C\" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();\n len += l;\n x = +p[5];\n y = +p[6];\n continue;\n }\n if (!istotal && !subpath) {\n point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);\n return {x: point.x, y: point.y, alph
57590a: point.alpha};\n }\n }\n len += l;\n x = +p[5];\n y = +p[6];\n }\n sp += p.shift() + p;\n }\n subpaths.end = sp;\n point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);\n point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});\n return point;\n };\n };\n var getTotalLength = getLengthFactory(1),\n getPointAtLength = getLengthFactory(),\n getSubpathsAtLength = getLengthFactory(0, 1);\n /*\\\n * Raphael.getTotalLength\n [ method ]\n **\n * Returns length of the given path in pixels.\n **\n > Parameters\n **\n - path (string) SVG path string.\n **\n = (number) length.\n \\*/\n R.getTotalLength = getTotalLength;\n /*\\\n * Raphael.getPointAtLength\n [ method ]\n **\n * Return coordinates of the point located at the given length on the given path.\n **\n > Parameters\n **\n - path (string) SVG path string\n - length (number)\n **\n = (object) representation of the point:\n o {\n o x: (number) x coordinate\n o y: (number) y coordinate\n o alpha: (number) angle of derivative\n o }\n \\*/\n R.getPointAtLength = getPointAtLength;\n /*\\\n * Raphael.getSubpath\n [ method ]\n **\n * Return subpath of a given path from given length to given length.\n **\n > Parameters\n **\n - path (string) SVG path string\n - from (number) position of the start of the segment\n - to (number) position of the end of the segment\n **\n = (string) pathstring for the segment\n \\*/\n R.getSubpath = function (path, from, to) {\n if (this.getTotalLength(path) - to < 1e-6) {\n return getSubpathsAtLength(path, from).end;\n }\n var a = getSubpathsAtLength(path, to, 1);\n return from ? getSubpathsAtLength(a, from).end : a;\n };\n /*\\\n * Element.getTotalLength\n [ method ]\n **\n * Returns length of the path in pixels. Only works for element of âpathâ type.\n = (number) length.\n \\*/\n elproto.getTotalLength = function () {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n if (this.node.getTotalLength) {\n return this.node.getTotalLength();\n }\n\n return getTotalLength(path);\n };\n /*\\\n * Element.getPointAtLength\n [ method ]\n **\n * Return coordinates of the point located at the given length on the given path. Only works for element of âpathâ type.\n **\n > Parameters\n **\n - length (number)\n **\n = (object) representation of the point:\n o {\n o x: (number) x coordinate\n o y: (number) y coordinate\n o alpha: (number) angle of derivative\n o }\n \\*/\n elproto.getPointAtLength = function (length) {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n return getPointAtLength(path, length);\n };\n /*\\\n * Element.getPath\n [ method ]\n **\n * Returns path of the element. Only works for elements of âpathâ type and simple elements like circle.\n = (object) path\n **\n \\*/\n elproto.getPath = function () {\n var path,\n getPath = R._getPath[this.type];\n\n if (this.type == \"text\" || this.type == \"set\") {\n return;\n }\n\n if (getPath) {\n path = getPath(this);\n }\n\n return path;\n };\n /*\\\n * Element.getSubpath\n [ method ]\n **\n * Return subpath of a given element from given length to given length. Only works for element of âpathâ type.\n **\n > Parameters\n **\n - from (number) position of the start of the segment\n - to (number) position of the end of the segment\n **\n = (string) pathstring for the segment\n \\*/\n elproto.getSubpath = function (from, to) {\n var path = this.getPath();\n if (!path) {\n return;\n }\n\n return R.getSubpath(path, from, to);\n };\n /*\\\n * Raphael.easing_formulas\n [ property ]\n **\n * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:\n # <ul>\n # <li>âlinearâ</li>\n # <li>â<â or âeaseInâ or âease-inâ</li>\n # <li>â>â or âeaseOutâ or âease-outâ</li>\n # <li>â<>â or âeaseInOutâ or âease-in-outâ</li>\n # <li>âbackInâ or âback-inâ</li>\n # <li>
57590âbackOutâ or âback-outâ</li>\n # <li>âelasticâ</li>\n # <li>âbounceâ</li>\n # </ul>\n # <p>See also <a href=\"http://raphaeljs.com/easing.html\">Easing demo</a>.</p>\n \\*/\n var ef = R.easing_formulas = {\n linear: function (n) {\n return n;\n },\n \"<\": function (n) {\n return pow(n, 1.7);\n },\n \">\": function (n) {\n return pow(n, .48);\n },\n \"<>\": function (n) {\n var q = .48 - n / 1.04,\n Q = math.sqrt(.1734 + q * q),\n x = Q - q,\n X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),\n y = -Q - q,\n Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),\n t = X + Y + .5;\n return (1 - t) * 3 * t * t + t * t * t;\n },\n backIn: function (n) {\n var s = 1.70158;\n return n * n * ((s + 1) * n - s);\n },\n backOut: function (n) {\n n = n - 1;\n var s = 1.70158;\n return n * n * ((s + 1) * n + s) + 1;\n },\n elastic: function (n) {\n if (n == !!n) {\n return n;\n }\n return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;\n },\n bounce: function (n) {\n var s = 7.5625,\n p = 2.75,\n l;\n if (n < (1 / p)) {\n l = s * n * n;\n } else {\n if (n < (2 / p)) {\n n -= (1.5 / p);\n l = s * n * n + .75;\n } else {\n if (n < (2.5 / p)) {\n n -= (2.25 / p);\n l = s * n * n + .9375;\n } else {\n n -= (2.625 / p);\n l = s * n * n + .984375;\n }\n }\n }\n return l;\n }\n };\n ef.easeIn = ef[\"ease-in\"] = ef[\"<\"];\n ef.easeOut = ef[\"ease-out\"] = ef[\">\"];\n ef.easeInOut = ef[\"ease-in-out\"] = ef[\"<>\"];\n ef[\"back-in\"] = ef.backIn;\n ef[\"back-out\"] = ef.backOut;\n\n var animationElements = [],\n requestAnimFrame = window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n function (callback) {\n setTimeout(callback, 16);\n },\n animation = function () {\n var Now = +new Date,\n l = 0;\n for (; l < animationElements.length; l++) {\n var e = animationElements[l];\n if (e.el.removed || e.paused) {\n continue;\n }\n var time = Now - e.start,\n ms = e.ms,\n easing = e.easing,\n from = e.from,\n diff = e.diff,\n to = e.to,\n t = e.t,\n that = e.el,\n set = {},\n now,\n init = {},\n key;\n if (e.initstatus) {\n time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;\n e.status = e.initstatus;\n delete e.initstatus;\n e.stop && animationElements.splice(l--, 1);\n } else {\n e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;\n }\n if (time < 0) {\n continue;\n }\n if (time < ms) {\n var pos = easing(time / ms);\n for (var attr in from) if (from[has](attr)) {\n switch (availableAnimAttrs[attr]) {\n case nu:\n now = +from[attr] + pos * ms * diff[attr];\n break;\n case \"colour\":\n now = \"rgb(\" + [\n upto255(round(from[attr].r + pos * ms * diff[attr].r)),\n upto255(round(from[attr].g + pos * ms * diff[attr].g)),\n upto255(round(from[attr].b + pos * ms * diff[attr].b))\n ].join(\",\") + \")\";\n break;\n case \"path\":\n now = [];\n for (var i = 0, ii = from[attr].length; i < ii;
57590 i++) {\n now[i] = [from[attr][i][0]];\n for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];\n }\n now[i] = now[i].join(S);\n }\n now = now.join(S);\n break;\n case \"transform\":\n if (diff[attr].real) {\n now = [];\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n now[i] = [from[attr][i][0]];\n for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];\n }\n }\n } else {\n var get = function (i) {\n return +from[attr][i] + pos * ms * diff[attr][i];\n };\n // now = [[\"r\", get(2), 0, 0], [\"t\", get(3), get(4)], [\"s\", get(0), get(1), 0, 0]];\n now = [[\"m\", get(0), get(1), get(2), get(3), get(4), get(5)]];\n }\n break;\n case \"csv\":\n if (attr == \"clip-rect\") {\n now = [];\n i = 4;\n while (i--) {\n now[i] = +from[attr][i] + pos * ms * diff[attr][i];\n }\n }\n break;\n default:\n var from2 = [][concat](from[attr]);\n now = [];\n i = that.paper.customAttributes[attr].length;\n while (i--) {\n now[i] = +from2[i] + pos * ms * diff[attr][i];\n }\n break;\n }\n set[attr] = now;\n }\n that.attr(set);\n (function (id, that, anim) {\n setTimeout(function () {\n eve(\"raphael.anim.frame.\" + id, that, anim);\n });\n })(that.id, that, e.anim);\n } else {\n (function(f, el, a) {\n setTimeout(function() {\n eve(\"raphael.anim.frame.\" + el.id, el, a);\n eve(\"raphael.anim.finish.\" + el.id, el, a);\n R.is(f, \"function\") && f.call(el);\n });\n })(e.callback, that, e.anim);\n that.attr(to);\n animationElements.splice(l--, 1);\n if (e.repeat > 1 && !e.next) {\n for (key in to) if (to[has](key)) {\n init[key] = e.totalOrigin[key];\n }\n e.el.attr(init);\n runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);\n }\n if (e.next && !e.stop) {\n runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);\n }\n }\n }\n animationElements.length && requestAnimFrame(animation);\n },\n upto255 = function (color) {\n return color > 255 ? 255 : color < 0 ? 0 : color;\n };\n /*\\\n * Element.animateWith\n [ method ]\n **\n * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.\n **\n > Parameters\n **\n - el (object) element to sync with\n - anim (object) animation to sync with\n - params (object) #optional final attributes for the element, see also @Element.attr\n - ms (number) #optional number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n * or\n - element (object) element to sync with\n - anim (object) animation to sync with\n - animation (object) #optional animation object, see @Raphael.animation\n **\n = (object) original element\n \\*/\n elproto.animateWith = function (el, anim, params, ms, easing, callback) {\n var element = this;
57590\n if (element.removed) {\n callback && callback.call(element);\n return element;\n }\n var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),\n x, y;\n runAnimation(a, element, a.percents[0], null, element.attr());\n for (var i = 0, ii = animationElements.length; i < ii; i++) {\n if (animationElements[i].anim == anim && animationElements[i].el == el) {\n animationElements[ii - 1].start = animationElements[i].start;\n break;\n }\n }\n return element;\n //\n //\n // var a = params ? R.animation(params, ms, easing, callback) : anim,\n // status = element.status(anim);\n // return this.animate(a).status(a, status * anim.ms / a.ms);\n };\n function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {\n var cx = 3 * p1x,\n bx = 3 * (p2x - p1x) - cx,\n ax = 1 - cx - bx,\n cy = 3 * p1y,\n by = 3 * (p2y - p1y) - cy,\n ay = 1 - cy - by;\n function sampleCurveX(t) {\n return ((ax * t + bx) * t + cx) * t;\n }\n function solve(x, epsilon) {\n var t = solveCurveX(x, epsilon);\n return ((ay * t + by) * t + cy) * t;\n }\n function solveCurveX(x, epsilon) {\n var t0, t1, t2, x2, d2, i;\n for(t2 = x, i = 0; i < 8; i++) {\n x2 = sampleCurveX(t2) - x;\n if (abs(x2) < epsilon) {\n return t2;\n }\n d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;\n if (abs(d2) < 1e-6) {\n break;\n }\n t2 = t2 - x2 / d2;\n }\n t0 = 0;\n t1 = 1;\n t2 = x;\n if (t2 < t0) {\n return t0;\n }\n if (t2 > t1) {\n return t1;\n }\n while (t0 < t1) {\n x2 = sampleCurveX(t2);\n if (abs(x2 - x) < epsilon) {\n return t2;\n }\n if (x > x2) {\n t0 = t2;\n } else {\n t1 = t2;\n }\n t2 = (t1 - t0) / 2 + t0;\n }\n return t2;\n }\n return solve(t, 1 / (200 * duration));\n }\n elproto.onAnimation = function (f) {\n f ? eve.on(\"raphael.anim.frame.\" + this.id, f) : eve.unbind(\"raphael.anim.frame.\" + this.id);\n return this;\n };\n function Animation(anim, ms) {\n var percents = [],\n newAnim = {};\n this.ms = ms;\n this.times = 1;\n if (anim) {\n for (var attr in anim) if (anim[has](attr)) {\n newAnim[toFloat(attr)] = anim[attr];\n percents.push(toFloat(attr));\n }\n percents.sort(sortByNumber);\n }\n this.anim = newAnim;\n this.top = percents[percents.length - 1];\n this.percents = percents;\n }\n /*\\\n * Animation.delay\n [ method ]\n **\n * Creates a copy of existing animation object with given delay.\n **\n > Parameters\n **\n - delay (number) number of ms to pass between animation start and actual animation\n **\n = (object) new altered Animation object\n | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);\n | circle1.animate(anim); // run the given animation immediately\n | circle2.animate(anim.delay(500)); // run the given animation after 500 ms\n \\*/\n Animation.prototype.delay = function (delay) {\n var a = new Animation(this.anim, this.ms);\n a.times = this.times;\n a.del = +delay || 0;\n return a;\n };\n /*\\\n * Animation.repeat\n [ method ]\n **\n * Creates a copy of existing animation object with given repetition.\n **\n > Parameters\n **\n - repeat (number) number iterations of animation. For infinite animation pass `Infinity`\n **\n = (object) new altered Animation object\n \\*/\n Animation.prototype.repeat = function (times) {\n var a = new Animation(this.anim, this.ms);\n a.del = this.del;\n a.times = math.floor(mmax(times, 0)) || 1;\n return a;\n };\n function runAnimation(anim, element, percent, status, totalOrigin, times) {\n percent = toFloat(percent);\n var params,\n isInAnim,\n isInAnimSet,\n percents = [],\n next,\n prev,\n timestamp,\n ms = anim.ms,\n from = {},\n to = {},\n diff = {};\n if (status) {\n for (i = 0, ii = animationElements.length; i < ii;
57590 i++) {\n var e = animationElements[i];\n if (e.el.id == element.id && e.anim == anim) {\n if (e.percent != percent) {\n animationElements.splice(i, 1);\n isInAnimSet = 1;\n } else {\n isInAnim = e;\n }\n element.attr(e.totalOrigin);\n break;\n }\n }\n } else {\n status = +to; // NaN\n }\n for (var i = 0, ii = anim.percents.length; i < ii; i++) {\n if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {\n percent = anim.percents[i];\n prev = anim.percents[i - 1] || 0;\n ms = ms / anim.top * (percent - prev);\n next = anim.percents[i + 1];\n params = anim.anim[percent];\n break;\n } else if (status) {\n element.attr(anim.anim[anim.percents[i]]);\n }\n }\n if (!params) {\n return;\n }\n if (!isInAnim) {\n for (var attr in params) if (params[has](attr)) {\n if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {\n from[attr] = element.attr(attr);\n (from[attr] == null) && (from[attr] = availableAttrs[attr]);\n to[attr] = params[attr];\n switch (availableAnimAttrs[attr]) {\n case nu:\n diff[attr] = (to[attr] - from[attr]) / ms;\n break;\n case \"colour\":\n from[attr] = R.getRGB(from[attr]);\n var toColour = R.getRGB(to[attr]);\n diff[attr] = {\n r: (toColour.r - from[attr].r) / ms,\n g: (toColour.g - from[attr].g) / ms,\n b: (toColour.b - from[attr].b) / ms\n };\n break;\n case \"path\":\n var pathes = path2curve(from[attr], to[attr]),\n toPath = pathes[1];\n from[attr] = pathes[0];\n diff[attr] = [];\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n diff[attr][i] = [0];\n for (var j = 1, jj = from[attr][i].length; j < jj; j++) {\n diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;\n }\n }\n break;\n case \"transform\":\n var _ = element._,\n eq = equaliseTransform(_[attr], to[attr]);\n if (eq) {\n from[attr] = eq.from;\n to[attr] = eq.to;\n diff[attr] = [];\n diff[attr].real = true;\n for (i = 0, ii = from[attr].length; i < ii; i++) {\n diff[attr][i] = [from[attr][i][0]];\n for (j = 1, jj = from[attr][i].length; j < jj; j++) {\n diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;\n }\n }\n } else {\n var m = (element.matrix || new Matrix),\n to2 = {\n _: {transform: _.transform},\n getBBox: function () {\n return element.getBBox(1);\n }\n };\n from[attr] = [\n m.a,\n m.b,\n m.c,\n m.d,\n m.e,\n m.f\n ];\n extractTransform(to2, to[attr]);\n to[attr] = to2._.transform;\n diff[attr] = [\n (to2.matrix.a - m.a) / ms,\n (to2.matrix.b - m.b) / ms,\n (to2.matrix.c - m.c) / ms,\n (to2.matrix.d - m.d) / ms,\n (to2.matrix.e - m.e) / ms,\n (to2.matrix.f - m.f) / ms\n ];\n // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];\n // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};\n // extractTransform(to2, to[attr]);\n // diff[attr] = [\n // (to2._.sx - _.sx) / ms,\n // (to2._.sy - _.sy) / ms,\n // (to2._.deg - _.deg) / ms,\n // (to2._.dx - _.dx) / ms,\n // (to2._.dy - _.dy) / ms\n // ];\n }\n break;\n case \"csv\":\n var values = Str(params[attr])[split](separator),\n from2 = Str(from[attr])[split](separator);\n if (attr == \"clip-rect\") {\n from[attr] = from2;\n diff[attr] = [];\n i = from2.length;\n while (i--) {\n diff[attr][i] = (values[i] - from[attr][i]) / ms;\n }\n }\n to[attr] = values;\n break;\n default:\n values = [][concat](params[attr]);\n from2 = [][concat](from[attr]);\n diff[attr] = [];\n i = element.paper.customAttributes[attr].length;\n while (i--) {\n diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;\n }\n break;\n }\n }\n }\n var easing = params.easing,\n easyeasy = R.easing_formulas[easing];\n if (!easyeasy) {\n easyeasy = Str(easing).match(bezierrg);\n if (easyeasy && easyeasy.length == 5) {\n var curve = easyeasy;\n easyeasy = function (t) {\n return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);\n };\n } else {\n easyeasy = pipe;\n }\n }\n timestamp = params.start || anim.start || +new Date;\n e = {\n anim: anim,\n percent: percent,\n timestamp: timestamp,\n start: timestamp + (anim.del || 0),\
57590n status: 0,\n initstatus: status || 0,\n stop: false,\n ms: ms,\n easing: easyeasy,\n from: from,\n diff: diff,\n to: to,\n el: element,\n callback: params.callback,\n prev: prev,\n next: next,\n repeat: times || anim.times,\n origin: element.attr(),\n totalOrigin: totalOrigin\n };\n animationElements.push(e);\n if (status && !isInAnim && !isInAnimSet) {\n e.stop = true;\n e.start = new Date - ms * status;\n if (animationElements.length == 1) {\n return animation();\n }\n }\n if (isInAnimSet) {\n e.start = new Date - e.ms * status;\n }\n animationElements.length == 1 && requestAnimFrame(animation);\n } else {\n isInAnim.initstatus = status;\n isInAnim.start = new Date - isInAnim.ms * status;\n }\n eve(\"raphael.anim.start.\" + element.id, element, anim);\n }\n /*\\\n * Raphael.animation\n [ method ]\n **\n * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.\n * See also @Animation.delay and @Animation.repeat methods.\n **\n > Parameters\n **\n - params (object) final attributes for the element, see also @Element.attr\n - ms (number) number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n **\n = (object) @Animation\n \\*/\n R.animation = function (params, ms, easing, callback) {\n if (params instanceof Animation) {\n return params;\n }\n if (R.is(easing, \"function\") || !easing) {\n callback = callback || easing || null;\n easing = null;\n }\n params = Object(params);\n ms = +ms || 0;\n var p = {},\n json,\n attr;\n for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat
57590(attr) + \"%\" != attr) {\n json = true;\n p[attr] = params[attr];\n }\n if (!json) {\n // if percent-like syntax is used and end-of-all animation callback used\n if(callback){\n // find the last one\n var lastKey = 0;\n for(var i in params){\n var percent = toInt(i);\n if(params[has](i) && percent > lastKey){\n lastKey = percent;\n }\n }\n lastKey += '%';\n // if already defined callback in the last keyframe, skip\n !params[lastKey].callback && (params[lastKey].callback = callback);\n }\n return new Animation(params, ms);\n } else {\n easing && (p.easing = easing);\n callback && (p.callback = callback);\n return new Animation({100: p}, ms);\n }\n };\n /*\\\n * Element.animate\n [ method ]\n **\n * Creates and starts animation for given element.\n **\n > Parameters\n **\n - params (object) final attributes for the element, see also @Element.attr\n - ms (number) number of milliseconds for animation to run\n - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic‐bezier(XX, XX, XX, XX)`\n - callback (function) #optional callback function. Will be called at the end of animation.\n * or\n - animation (object) animation object, see @Raphael.animation\n **\n = (object) original element\n \\*/\n elproto.animate = function (params, ms, easing, callback) {\n var element = this;
57590\n if (element.removed) {\n callback && callback.call(element);\n return element;\n }\n var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);\n runAnimation(anim, element, anim.percents[0], null, element.attr());\n return element;\n };\n /*\\\n * Element.setTime\n [ method ]\n **\n * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.\n **\n > Parameters\n **\n - anim (object) animation object\n - value (number) number of milliseconds from the beginning of the animation\n **\n = (object) original element if `value` is specified\n * Note, that during animation following events are triggered:\n *\n * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`.\n \\*/\n elproto.setTime = function (anim, value) {\n if (anim && value != null) {\n this.status(anim, mmin(value, anim.ms) / anim.ms);\n }\n return this;\n };\n /*\\\n * Element.status\n [ method ]\n **\n * Gets or sets the status of animation of the element.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n - value (number) #optional 0 â 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.\n **\n = (number) status\n * or\n = (array) status if `anim` is not specified. Array of objects in format:\n o {\n o anim: (object) animation object\n o status: (number) status\n o }\n * or\n = (object) original element if `value` is specified\n \\*/\n elproto.status = function (anim, value) {\n var out = [],\n i = 0,\n len,\n e;\n if (value != null) {\n runAnimation(anim, this, -1, mmin(value, 1));\n return this;\n } else {\n len = animationElements.length;\n for (; i < len; i++) {\n e = animationElements[i];\n if (e.el.id == this.id && (!anim || e.anim == anim)) {\n if (anim) {\n return e.status;\n }\n out.push({\n anim: e.anim,\n status: e.status\n });\n }\n }\n if (anim) {\n return 0;\n }\n return out;\n }\n };\n /*\\\n * Element.pause\n [ method ]\n **\n * Stops animation of the element with ability to resume it later on.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.pause = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n if (eve(\"raphael.anim.pause.\" + this.id, this, animationElements[i].anim) !== false) {\n animationElements[i].paused = true;\n }\n }\n return this;\n };\n /*\\\n * Element.resume\n [ method ]\n **\n * Resumes animation if it was paused with @Element.pause method.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.resume = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n var e = animationElements[i];\n if (eve(\"raphael.anim.resume.\" + this.id, this, e.anim) !== false) {\n delete e.paused;\n this.status(e.anim, e.status);\n }\n }\n return this;\n };\n /*\\\n * Element.stop\n [ method ]\n **\n * Stops animation of the element.\n **\n > Parameters\n **\n - anim (object) #optional animation object\n **\n = (object) original element\n \\*/\n elproto.stop = function (anim) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {\n if (eve(\"raphael.anim.stop.\" + this.id, this, animationElements[i].anim) !== false) {\n animationElements.splice(i--, 1);\n }\n }\n return this;\n };\n function stopAnimation(paper) {\n for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {\n animationElements.splice(i--, 1);\n }\n }\n eve.on(\"raphael.remove\", stopAnimation);\n eve.on(\"raphael.clear\", stopAnimation);\n elproto.toString = function () {\n return \"Rapha\\xebl\\u2019s object\";\n };\n\n // Set\n var Set = function (items) {\n this.items = [];\n this.length = 0;\n this.type = \"set\";\n if (items) {\n for (var i = 0, ii = items.length; i < ii;
57590 i++) {\n if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {\n this[this.items.length] = this.items[this.items.length] = items[i];\n this.length++;\n }\n }\n }\n },\n setproto = Set.prototype;\n /*\\\n * Set.push\n [ method ]\n **\n * Adds each argument to the current set.\n = (object) original element\n \\*/\n setproto.push = function () {\n var item,\n len;\n for (var i = 0, ii = arguments.length; i < ii; i++) {\n item = arguments[i];\n if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {\n len = this.items.length;\n this[len] = this.items[len] = item;\n this.length++;\n }\n }\n return this;\n };\n /*\\\n * Set.pop\n [ method ]\n **\n * Removes last element and returns it.\n = (object) element\n \\*/\n setproto.pop = function () {\n this.length && delete this[this.length--];\n return this.items.pop();\n };\n /*\\\n * Set.forEach\n [ method ]\n **\n * Executes given function for each element in the set.\n *\n * If function returns `false` it will stop loop running.\n **\n > Parameters\n **\n - callback (function) function to run\n - thisArg (object) context object for the callback\n = (object) Set object\n \\*/\n setproto.forEach = function (callback, thisArg) {\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n if (callback.call(thisArg, this.items[i], i) === false) {\n return this;\n }\n }\n return this;\n };\n for (var method in elproto) if (elproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname][apply](el, arg);\n });\n };\n })(method);\n }\n setproto.attr = function (name, value) {\n if (name && R.is(name, array) && R.is(name[0], \"object\")) {\n for (var j = 0, jj = name.length; j < jj; j++) {\n this.items[j].attr(name[j]);\n }\n } else {\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n this.items[i].attr(name, value);\n }\n }\n return this;\n };\n /*\\\n * Set.clear\n [ method ]\n **\n * Removes all elements from the set\n \\*/\n setproto.clear = function () {\n while (this.length) {\n this.pop();\n }\n };\n /*\\\n * Set.splice\n [ method ]\n **\n * Removes given element from the set\n **\n > Parameters\n **\n - index (number) position of the deletion\n - count (number) number of element to remove\n - insertion⦠(object) #optional elements to insert\n = (object) set elements that were deleted\n \\*/\n setproto.splice = function (index, count, insertion) {\n index = index < 0 ? mmax(this.length + index, 0) : index;\n count = mmax(0, mmin(this.length - index, count));\n var tail = [],\n todel = [],\n args = [],\n i;\n for (i = 2; i < arguments.length; i++) {\n args.push(arguments[i]);\n }\n for (i = 0; i < count; i++) {\n todel.push(this[index + i]);\n }\n for (; i < this.length - index; i++) {\n tail.push(this[index + i]);\n }\n var arglen = args.length;\n for (i = 0; i < arglen + tail.length; i++) {\n this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];\n }\n i = this.items.length = this.length -= count - arglen;\n while (this[i]) {\n delete this[i++];\n }\n return new Set(todel);\n };\n /*\\\n * Set.exclude\n [ method ]\n **\n * Removes given element from the set\n **\n > Parameters\n **\n - element (object) element to remove\n = (boolean) `true` if object was found & removed from the set\n \\*/\n setproto.exclude = function (el) {\n for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {\n this.splice(i, 1);\n return true;\n }\n };\n setproto.animate = function (params, ms, easing, callback) {\n (R.is(easing, \"function\") || !easing) && (callback = easing || null);\n var len = this.items.length,\n i = len,\n item,\n set = this,\n collector;\n if (!len) {\n return this;\n }\n callback && (collector = function () {\n !--len && callback.call(set);\n });\n easing = R.is(easing, string) ? easing : collector;\n var anim = R.animation(params, ms, easing, collector);\n item = this.items[--i].animate(anim);\n while (i--) {\n this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);\n (this.items[i] && !this.items[i].removed) || len--;\n }\n return this;\n };\n setproto.insertAfter = function (el) {\n var i = this.items.length;\n while (i--) {\n this.items[i].insertAfter(el);\n }\n return this;\n };\n setproto.getBBox = function () {\n var x = [],\n y = [],\n x2 = [],\n y2 = [];\n for (var i = this.items.length; i--;
57590) if (!this.items[i].removed) {\n var box = this.items[i].getBBox();\n x.push(box.x);\n y.push(box.y);\n x2.push(box.x + box.width);\n y2.push(box.y + box.height);\n }\n x = mmin[apply](0, x);\n y = mmin[apply](0, y);\n x2 = mmax[apply](0, x2);\n y2 = mmax[apply](0, y2);\n return {\n x: x,\n y: y,\n x2: x2,\n y2: y2,\n width: x2 - x,\n height: y2 - y\n };\n };\n setproto.clone = function (s) {\n s = this.paper.set();\n for (var i = 0, ii = this.items.length; i < ii; i++) {\n s.push(this.items[i].clone());\n }\n return s;\n };\n setproto.toString = function () {\n return \"Rapha\\xebl\\u2018s set\";\n };\n\n setproto.glow = function(glowConfig) {\n var ret = this.paper.set();\n this.forEach(function(shape, index){\n var g = shape.glow(glowConfig);\n if(g != null){\n g.forEach(function(shape2, index2){\n ret.push(shape2);\n });\n }\n });\n return ret;\n };\n\n\n /*\\\n * Set.isPointInside\n [ method ]\n **\n * Determine if given point is inside this setâs elements\n **\n > Parameters\n **\n - x (number) x coordinate of the point\n - y (number) y coordinate of the point\n = (boolean) `true` if point is inside any of the set's elements\n \\*/\n setproto.isPointInside = function (x, y) {\n var isPointInside = false;\n this.forEach(function (el) {\n if (el.isPointInside(x, y)) {\n isPointInside = true;\n return false; // stop loop\n }\n });\n return isPointInside;\n };\n\n /*\\\n * Raphael.registerFont\n [ method ]\n **\n * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufónâs font file.\n * Returns original parameter, so it could be used with chaining.\n # <a href=\"http://wiki.github.com/sorccu/cufon/about\">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a>\n **\n > Parameters\n **\n - font (object) the font to register\n = (object) the font you passed in\n > Usage\n | Cufon.registerFont(Raphael.registerFont({â¦}));\n \\*/\n R.registerFont = function (font) {\n if (!font.face) {\n return font;\n }\n this.fonts = this.fonts || {};\n var fontcopy = {\n w: font.w,\n face: {},\n glyphs: {}\n },\n family = font.face[\"font-family\"];\n for (var prop in font.face) if (font.face[has](prop)) {\n fontcopy.face[prop] = font.face[prop];\n }\n if (this.fonts[family]) {\n this.fonts[family].push(fontcopy);\n } else {\n this.fonts[family] = [fontcopy];\n }\n if (!font.svg) {\n fontcopy.face[\"units-per-em\"] = toInt(font.face[\"units-per-em\"], 10);\n for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {\n var path = font.glyphs[glyph];\n fontcopy.glyphs[glyph] = {\n w: path.w,\n k: {},\n d: path.d && \"M\" + path.d.replace(/[mlcxtrv]/g, function (command) {\n return {l: \"L\", c: \"C\", x: \"z\", t: \"m\", r: \"l\", v: \"c\"}[command] || \"M\";\n }) + \"z\"\n };\n if (path.k) {\n for (var k in path.k) if (path[has](k)) {\n fontcopy.glyphs[glyph].k[k] = path.k[k];\n }\n }\n }\n }\n return font;\n };\n /*\\\n * Paper.getFont\n [ method ]\n **\n * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like âMyriadâ for âMyriad Proâ.\n **\n > Parameters\n **\n - family (string) font family name or any word from it\n - weight (string) #optional font weight\n - style (string) #optional font style\n - stretch (string) #optional font stretch\n = (object) the font object\n > Usage\n | paper.print(100, 100, \"Test string\", paper.getFont(\"Times\", 800), 30);\n \\*/\n paperproto.getFont = function (family, weight, style, stretch) {\n stretch = stretch || \"
57590normal\";\n style = style || \"normal\";\n weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;\n if (!R.fonts) {\n return;\n }\n var font = R.fonts[family];\n if (!font) {\n var name = new RegExp(\"(^|\\\\s)\" + family.replace(/[^\\w\\d\\s+!~.:_-]/g, E) + \"(\\\\s|$)\", \"i\");\n for (var fontName in R.fonts) if (R.fonts[has](fontName)) {\n if (name.test(fontName)) {\n font = R.fonts[fontName];\n break;\n }\n }\n }\n var thefont;\n if (font) {\n for (var i = 0, ii = font.length; i < ii; i++) {\n thefont = font[i];\n if (thefont.face[\"font-weight\"] == weight && (thefont.face[\"font-style\"] == style || !thefont.face[\"font-style\"]) && thefont.face[\"font-stretch\"] == stretch) {\n break;\n }\n }\n }\n return thefont;\n };\n /*\\\n * Paper.print\n [ method ]\n **\n * Creates path that represent given text written using given font at given position with given size.\n * Result of the method is path element that contains whole text as a separate path.\n **\n > Parameters\n **\n - x (number) x position of the text\n - y (number) y position of the text\n - string (string) text to print\n - font (object) font object, see @Paper.getFont\n - size (number) #optional size of the font, default is `16`\n - origin (string) #optional could be `\"baseline\"` or `\"middle\"`, default is `\"middle\"`\n - letter_spacing (number) #optional number in range `-1..1`, default is `0`\n - line_spacing (number) #optional number in range `1..3`, default is `1`\n = (object) resulting path element, which consist of all letters\n > Usage\n | var txt = r.print(10, 50, \"print\", r.getFont(\"Museo\"), 30).attr({fill: \"#fff\"});\n \\*/\n paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {\n origin = origin || \"middle\"; // baseline|middle\n letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);\n line_spacing = mmax(mmin(line_spacing || 1, 3), 1);\n var letters = Str(string)[split](E),\n shift = 0,\n notfirst = 0,\n path = E,\n scale;\n R.is(font, \"string\") && (font = this.getFont(font));\n if (font) {\n scale = (size || 16) / font.face[\"units-per-em\"];\n var bb = font.face.bbox[split](separator),\n top = +bb[0],\n lineHeight = bb[3] - bb[1],\n shifty = 0,\n height = +bb[1] + (origin == \"baseline\" ? lineHeight + (+font.face.descent) : lineHeight / 2);\n for (var i = 0, ii = letters.length; i < ii; i++) {\n if (letters[i] == \"\\n\") {\n shift = 0;\n curr = 0;\n notfirst = 0;\n shifty += lineHeight * line_spacing;\n } else {\n var prev = notfirst && font.glyphs[letters[i - 1]] || {},\n curr = font.glyphs[letters[i]];\n shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;\n notfirst = 1;\n }\n if (curr && curr.d) {\n path += R.transformPath(curr.d, [\"t\", shift * scale, shifty * scale, \"s\", scale, scale, top, height, \"t\", (x - top) / scale, (y - height) / scale]);\n }\n }\n }\n return this.path(path).attr({\n fill: \"#000\",\n stroke: \"none\"\n });\n };\n\n /*\\\n * Paper.add\n [ method ]\n **\n * Imports elements in JSON array in format `{type: type, <attributes>}`\n **\n > Parameters\n **\n - json (array)\n = (object) resulting set of imported elements\n > Usage\n | paper.add([\n | {\n | type: \"circle\",\n | cx: 10,\n | cy: 10,\n | r: 5\n | },\n | {\n | type: \"rect\",\n | x: 10,\n | y: 10,\n | width: 10,\n | height: 10,\n | fill: \"#fc0\"\n | }\n | ]);\n \\*/\n paperproto.add = function (json) {\n if (R.is(json, \"array\")) {\n var res = this.set(),\n i = 0,\n ii = json.length,\n j;\n for (; i < ii;
57590 i++) {\n j = json[i] || {};\n elements[has](j.type) && res.push(this[j.type]().attr(j));\n }\n }\n return res;\n };\n\n /*\\\n * Raphael.format\n [ method ]\n **\n * Simple format function. Replaces construction of type â`{<number>}`â to the corresponding argument.\n **\n > Parameters\n **\n - token (string) string to format\n - ⦠(string) rest of arguments will be treated as parameters for replacement\n = (string) formated string\n > Usage\n | var x = 10,\n | y = 20,\n | width = 40,\n | height = 50;\n | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n | paper.path(Raphael.format(\"M{0},{1}h{2}v{3}h{4}z\", x, y, width, height, -width));\n \\*/\n R.format = function (token, params) {\n var args = R.is(params, array) ? [0][concat](params) : arguments;\n token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {\n return args[++i] == null ? E : args[i];\n }));\n return token || E;\n };\n /*\\\n * Raphael.fullfill\n [ method ]\n **\n * A little bit more advanced format function than @Raphael.format. Replaces construction of type â`{<name>}
57590`â to the corresponding argument.\n **\n > Parameters\n **\n - token (string) string to format\n - json (object) object which properties will be used as a replacement\n = (string) formated string\n > Usage\n | // this will draw a rectangular shape equivalent to \"M10,20h40v50h-40z\"\n | paper.path(Raphael.fullfill(\"M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z\", {\n | x: 10,\n | y: 20,\n | dim: {\n | width: 40,\n | height: 50,\n | \"negative width\": -40\n | }\n | }));\n \\*/\n R.fullfill = (function () {\n var tokenRegex = /\\{([^\\}]+)\\}/g,\n objNotationRegex = /(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g, // matches .xxxxx or [\"xxxxx\"] to run over object properties\n replacer = function (all, key, obj) {\n var res = obj;\n key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {\n name = name || quotedName;\n if (res) {\n if (name in res) {\n res = res[name];\n }\n typeof res == \"function\" && isFunc && (res = res());\n }\n });\n res = (res == null || res == obj ? all : res) + \"\";\n return res;\n };\n return function (str, obj) {\n return String(str).replace(tokenRegex, function (all, key) {\n return replacer(all, key, obj);\n });\n };\n })();\n /*\\\n * Raphael.ninja\n [ method ]\n **\n * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.\n * Beware, that in this case plugins could stop working, because they are depending on global variable existence.\n **\n = (object) Raphael object\n > Usage\n | (function (local_raphael) {\n | var paper = local_raphael(10, 10, 320, 200);\n | â¦\n | })(Raphael.ninja());\n \\*/\n R.ninja = function () {\n if (oldRaphael.was) {\n g.win.Raphael = oldRaphael.is;\n } else {\n // IE8 raises an error when deleting window property\n window.Raphael = undefined;\n try {\n delete window.Raphael;\n } catch(e) {}\n }\n return R;\n };\n /*\\\n * Raphael.st\n [ property (object) ]\n **\n * You can add your own method to elements and sets. It is wise to add a set method for each element method\n * you added, so you will be able to call the same method on sets too.\n **\n * See also @Raphael.el.\n > Usage\n | Raphael.el.red = function () {\n | this.attr({fill: \"#f00\"});\n | };\n | Raphael.st.red = function () {\n | this.forEach(function (el) {\n | el.red();\n | });\n | };\n | // then use it\n | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();\n \\*/\n R.st = setproto;\n\n eve.on(\"raphael.DOMload\", function () {\n loaded = true;\n });\n\n // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html\n (function (doc, loaded, f) {\n if (doc.readyState == null && doc.addEventListener){\n doc.addEventListener(loaded, f = function () {\n doc.removeEventListener(loaded, f, false);\n doc.readyState = \"complete\";\n }, false);\n doc.readyState = \"loading\";\n }\n function isLoaded() {\n (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve(\"raphael.DOMload\");\n }\n isLoaded();\n })(document, \"DOMContentLoaded\");\n\n return R;\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5jb3JlLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vUmFwaGFlbC8uL2Rldi9yYXBoYWVsLmNvcmUuanM/OTRkOSJdLCJzb3VyY2VzQ29udGVudCI6WyJkZWZpbmUoW1wiZXZlXCJdLCBmdW5jdGlvbihldmUpIHtcblxuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGEgY2FudmFzIG9iamVjdCBvbiB3aGljaCB0byBkcmF3LlxuICAgICAqIFlvdSBtdXN0IGRvIHRoaXMgZmlyc3QsIGFzIGFsbCBmdXR1cmUgY2FsbHMgdG8gZHJhd2luZyBtZXRob2RzXG4gICAgICogZnJvbSB0aGlzIGluc3RhbmNlIHdpbGwgYmUgYm91bmQgdG8gdGhpcyBjYW52YXMuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGNvbnRhaW5lciAoSFRNTEVsZW1lbnR8c3RyaW5nKSBET00gZWxlbWVudCBvciBpdHMgSUQgd2hpY2ggaXMgZ29pbmcgdG8gYmUgYSBwYXJlbnQgZm9yIGRyYXdpbmcgc3VyZmFjZVxuICAgICAtIHdpZHRoIChudW1iZXIpXG4gICAgIC0gaGVpZ2h0IChudW1iZXIpXG4gICAgIC0gY2FsbGJhY2sgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgY2FsbGJhY2sgZnVuY3Rpb24gd2hpY2ggaXMgZ29pbmcgdG8gYmUgZXhlY3V0ZWQgaW4gdGhlIGNvbnRleHQgb2YgbmV3bHkgY3JlYXRlZCBwYXBlclxuICAgICAqIG9yXG4gICAgIC0geCAobnVtYmVyKVxuICAgICAtIHkgKG51bWJlcilcbiAgICAgLSB3aWR0aCAobnVtYmVyKVxuICAgICAtIGhlaWdodCAobnVtYmVyKVxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHdoaWNoIGlzIGdvaW5nIHRvIGJlIGV4ZWN1dGVkIGluIHRoZSBjb250ZXh0IG9mIG5ld2x5IGNyZWF0ZWQgcGFwZXJcbiAgICAgKiBvclxuICAgICAtIGFsbCAoYXJyYXkpIChmaXJzdCAzIG9yIDQgZWxlbWVudHMgaW4gdGhlIGFycmF5IGFyZSBlcXVhbCB0byBbY29udGFpbmVySUQsIHdpZHRoLCBoZWlnaHRdIG9yIFt4LCB5LCB3aWR0aCwgaGVpZ2h0XS4gVGhlIHJlc3QgYXJlIGVsZW1lbnQgZGVzY3JpcHRpb25zIGluIGZvcm1hdCB7dHlwZTogdHlwZSwgPGF0dHJpYnV0ZXM+fSkuIFNlZSBAUGFwZXIuYWRkLlxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uIHdoaWNoIGlzIGdvaW5nIHRvIGJlIGV4ZWN1dGVkIGluIHRoZSBjb250ZXh0IG9mIG5ld2x5IGNyZWF0ZWQgcGFwZXJcbiAgICAgKiBvclxuICAgICAtIG9uUmVhZHlDYWxsYmFjayAoZnVuY3Rpb24pIGZ1bmN0aW9uIHRoYXQgaXMgZ29pbmcgdG8gYmUgY2FsbGVkIG9uIERPTSByZWFkeSBldmVudC4gWW91IGNhbiBhbHNvIHN1YnNjcmliZSB0byB0aGlzIGV2ZW50IHZpYSBFdmXigJlzIOKAnERPTUxvYWTigJ0gZXZlbnQuIEluIHRoaXMgY2FzZSBtZXRob2QgcmV0dXJucyBgdW5kZWZpbmVkYC5cbiAgICAgPSAob2JqZWN0KSBAUGFwZXJcbiAgICAgPiBVc2FnZVxuICAgICB8IC8vIEVhY2ggb2YgdGhlIGZvbGxvd2luZyBleGFtcGxlcyBjcmVhdGUgYSBjYW52YXNcbiAgICAgfCAvLyB0aGF0IGlzIDMyMHB4IHdpZGUgYnkgMjAwcHggaGlnaC5cbiAgICAgfCAvLyBDYW52YXMgaXMgY3JlYXRlZCBhdCB0aGUgdmlld3BvcnTigJlzIDEwLDUwIGNvb3JkaW5hdGUuXG4gICAgI
57590HwgdmFyIHBhcGVyID0gUmFwaGFlbCgxMCwgNTAsIDMyMCwgMjAwKTtcbiAgICAgfCAvLyBDYW52YXMgaXMgY3JlYXRlZCBhdCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSAjbm90ZXBhZCBlbGVtZW50XG4gICAgIHwgLy8gKG9yIGl0cyB0b3AgcmlnaHQgY29ybmVyIGluIGRpcj1cInJ0bFwiIGVsZW1lbnRzKVxuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJub3RlcGFkXCIpLCAzMjAsIDIwMCk7XG4gICAgIHwgLy8gU2FtZSBhcyBhYm92ZVxuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoXCJub3RlcGFkXCIsIDMyMCwgMjAwKTtcbiAgICAgfCAvLyBJbWFnZSBkdW1wXG4gICAgIHwgdmFyIHNldCA9IFJhcGhhZWwoW1wibm90ZXBhZFwiLCAzMjAsIDIwMCwge1xuICAgICB8ICAgICB0eXBlOiBcInJlY3RcIixcbiAgICAgfCAgICAgeDogMTAsXG4gICAgIHwgICAgIHk6IDEwLFxuICAgICB8ICAgICB3aWR0aDogMjUsXG4gICAgIHwgICAgIGhlaWdodDogMjUsXG4gICAgIHwgICAgIHN0cm9rZTogXCIjZjAwXCJcbiAgICAgfCB9LCB7XG4gICAgIHwgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICB8ICAgICB4OiAzMCxcbiAgICAgfCAgICAgeTogNDAsXG4gICAgIHwgICAgIHRleHQ6IFwiRHVtcFwiXG4gICAgIHwgfV0pO1xuICAgIFxcKi9cbiAgICBmdW5jdGlvbiBSKGZpcnN0KSB7XG4gICAgICAgIGlmIChSLmlzKGZpcnN0LCBcImZ1bmN0aW9uXCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9hZGVkID8gZmlyc3QoKSA6IGV2ZS5vbihcInJhcGhhZWwuRE9NbG9hZFwiLCBmaXJzdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoUi5pcyhmaXJzdCwgYXJyYXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gUi5fZW5naW5lLmNyZWF0ZVthcHBseV0oUiwgZmlyc3Quc3BsaWNlKDAsIDMgKyBSLmlzKGZpcnN0WzBdLCBudSkpKS5hZGQoZmlyc3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgaWYgKFIuaXMoYXJnc1thcmdzLmxlbmd0aCAtIDFdLCBcImZ1bmN0aW9uXCIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGYgPSBhcmdzLnBvcCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZWQgPyBmLmNhbGwoUi5fZW5naW5lLmNyZWF0ZVthcHBseV0oUiwgYXJncykpIDogZXZlLm9uKFwicmFwaGFlbC5ET01sb2FkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgZi5jYWxsKFIuX2VuZ2luZS5jcmVhdGVbYXBwbHldKFIsIGFyZ3MpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFIuX2VuZ2luZS5jcmVhdGVbYXBwbHldKFIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgUi52ZXJzaW9uID0gXCIyLjIuMFwiO1xuICAgIFIuZXZlID0gZXZlO1xuICAgIHZhciBsb2FkZWQsXG4gICAgICAgIHNlcGFyYXRvciA9IC9bLCBdKy8sXG4gICAgICAgIGVsZW1lbnRzID0ge2NpcmNsZTogMSwgcmVjdDogMSwgcGF0aDogMSwgZWxsaXBzZTogMSwgdGV4dDogMSwgaW1hZ2U6IDF9LFxuICAgICAgICBmb3JtYXRyZyA9IC9cXHsoXFxkKylcXH0vZyxcbiAgICAgICAgcHJvdG8gPSBcInByb3RvdHlwZVwiLFxuICAgICAgICBoYXMgPSBcImhhc093blByb3BlcnR5XCIsXG4gICAgICAgIGcgPSB7XG4gICAgICAgICAgICBkb2M6IGRvY3VtZW50LFxuICAgICAgICAgICAgd2luOiB3aW5kb3dcbiAgICAgICAgfSxcbiAgICAgICAgb2xkUmFwaGFlbCA9IHtcbiAgICAgICAgICAgIHdhczogT2JqZWN0LnByb3RvdHlwZVtoYXNdLmNhbGwoZy53aW4sIFwiUmFwaGFlbFwiKSxcbiAgICAgICAgICAgIGlzOiBnLndpbi5SYXBoYWVsXG4gICAgICAgIH0sXG4gICAgICAgIFBhcGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLypcXFxuICAgICAgICAgICAgICogUGFwZXIuY2FcbiAgICAgICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICAgICAqKlxuICAgICAgICAgICAgICogU2hvcnRjdXQgZm9yIEBQYXBlci5jdXN0b21BdHRyaWJ1dGVzXG4gICAgICAgICAgICBcXCovXG4gICAgICAgICAgICAvKlxcXG4gICAgICAgICAgICAgKiBQYXBlci5jdXN0b21BdHRyaWJ1dGVzXG4gICAgICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAgICAgKipcbiAgICAgICAgICAgICAqIElmIHlvdSBoYXZlIGEgc2V0IG9mIGF0dHJpYnV0ZXMgdGhhdCB5b3Ugd291bGQgbGlrZSB0byByZXByZXNlbnRcbiAgICAgICAgICAgICAqIGFzIGEgZnVuY3Rpb24gb2Ygc29tZSBudW1iZXIgeW91IGNhbiBkbyBpdCBlYXNpbHkgd2l0aCBjdXN0b20gYXR0cmlidXRlczpcbiAgICAgICAgICAgICA+IFVzYWdlXG4gICAgICAgICAgICAgfCBwYXBlci5jdXN0b21BdHRyaWJ1dGVzLmh1ZSA9IGZ1bmN0aW9uIChudW0pIHtcbiAgICAgICAgICAgICB8ICAgICBudW0gPSBudW0gJSAxO1xuICAgICAgICAgICAgIHwgICAgIHJldHVybiB7ZmlsbDogXCJoc2IoXCIgKyBudW0gKyBcIiwgMC43NSwgMSlcIn07XG4gICAgICAgICAgICAgfCB9O1xuICAgICAgICAgICAgIHwgLy8gQ3VzdG9tIGF0dHJpYnV0ZSDigJxodWXigJ0gd2lsbCBjaGFuZ2UgZmlsbFxuICAgICAgICAgICAgIHwgLy8gdG8gYmUgZ2l2ZW4gaHVlIHdpdGggZml4ZWQgc2F0dXJhdGlvbiBhbmQgYnJpZ2h0bmVzcy5cbiAgICAgICAgICAgICB8IC8vIE5vdyB5b3UgY2FuIHVzZSBpdCBsaWtlIHRoaXM6XG4gICAgICAgICAgICAgfCB2YXIgYyA9IHBhcGVyLmNpcmNsZSgxMCwgMTAsIDEwKS5hdHRyKHtodWU6IC40NX0pO1xuICAgICAgICAgICAgIHwgLy8gb3IgZXZlbiBsaWtlIHRoaXM6XG4gICAgICAgICAgICAgfCBjLmFuaW1hdGUoe2h1ZTogMX0sIDFlMyk7XG4gICAgICAgICAgICAgfFxuICAgICAgICAgICAgIHwgLy8gWW91IGNvdWxkIGFsc28gY3JlYXRlIGN1c3RvbSBhdHRyaWJ1dGVcbiAgICAgICAgICAgICB8IC8vIHdpdGggbXVsdGlwbGUgcGFyYW1ldGVyczpcbiAgICAgICAgICAgICB8IHBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMuaHNiID0gZnVuY3Rpb24gKGgsIHMsIGIpIHtcbiAgICAgICAgICAgICB8ICAgICByZXR1cm4ge2ZpbGw6IFwiaHNiKFwiICsgW2gsIHMsIGJdLmpvaW4oXCIsXCIpICsgXCIpXCJ9O1xuICAgICAgICAgICAgI
57590HwgfTtcbiAgICAgICAgICAgICB8IGMuYXR0cih7aHNiOiBcIjAuNSAuOCAxXCJ9KTtcbiAgICAgICAgICAgICB8IGMuYW5pbWF0ZSh7aHNiOiBbMSwgMCwgMC41XX0sIDFlMyk7XG4gICAgICAgICAgICBcXCovXG4gICAgICAgICAgICB0aGlzLmNhID0gdGhpcy5jdXN0b21BdHRyaWJ1dGVzID0ge307XG4gICAgICAgIH0sXG4gICAgICAgIHBhcGVycHJvdG8sXG4gICAgICAgIGFwcGVuZENoaWxkID0gXCJhcHBlbmRDaGlsZFwiLFxuICAgICAgICBhcHBseSA9IFwiYXBwbHlcIixcbiAgICAgICAgY29uY2F0ID0gXCJjb25jYXRcIixcbiAgICAgICAgLy90YWtlbiBmcm9tIE1vZGVybml6ciB0b3VjaCB0ZXN0OiBodHRwczovL2dpdGh1Yi5jb20vTW9kZXJuaXpyL01vZGVybml6ci9ibG9iL21hc3Rlci9mZWF0dXJlLWRldGVjdHMvdG91Y2hldmVudHMuanMjTDQwXG4gICAgICAgIHN1cHBvcnRzVG91Y2ggPSAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93KSB8fCB3aW5kb3cuVG91Y2hFdmVudCB8fCB3aW5kb3cuRG9jdW1lbnRUb3VjaCAmJiBkb2N1bWVudCBpbnN0YW5jZW9mIERvY3VtZW50VG91Y2gsXG4gICAgICAgIEUgPSBcIlwiLFxuICAgICAgICBTID0gXCIgXCIsXG4gICAgICAgIFN0ciA9IFN0cmluZyxcbiAgICAgICAgc3BsaXQgPSBcInNwbGl0XCIsXG4gICAgICAgIGV2ZW50cyA9IFwiY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNlbW92ZSBtb3VzZW91dCBtb3VzZW92ZXIgbW91c2V1cCB0b3VjaHN0YXJ0IHRvdWNobW92ZSB0b3VjaGVuZCB0b3VjaGNhbmNlbFwiW3NwbGl0XShTKSxcbiAgICAgICAgdG91Y2hNYXAgPSB7XG4gICAgICAgICAgICBtb3VzZWRvd246IFwidG91Y2hzdGFydFwiLFxuICAgICAgICAgICAgbW91c2Vtb3ZlOiBcInRvdWNobW92ZVwiLFxuICAgICAgICAgICAgbW91c2V1cDogXCJ0b3VjaGVuZFwiXG4gICAgICAgIH0sXG4gICAgICAgIGxvd2VyQ2FzZSA9IFN0ci5wcm90b3R5cGUudG9Mb3dlckNhc2UsXG4gICAgICAgIG1hdGggPSBNYXRoLFxuICAgICAgICBtbWF4ID0gbWF0aC5tYXgsXG4gICAgICAgIG1taW4gPSBtYXRoLm1pbixcbiAgICAgICAgYWJzID0gbWF0aC5hYnMsXG4gICAgICAgIHBvdyA9IG1hdGgucG93LFxuICAgICAgICBQSSA9IG1hdGguUEksXG4gICAgICAgIG51ID0gXCJudW1iZXJcIixcbiAgICAgICAgc3RyaW5nID0gXCJzdHJpbmdcIixcbiAgICAgICAgYXJyYXkgPSBcImFycmF5XCIsXG4gICAgICAgIHRvU3RyaW5nID0gXCJ0b1N0cmluZ1wiLFxuICAgICAgICBmaWxsU3RyaW5nID0gXCJmaWxsXCIsXG4gICAgICAgIG9iamVjdFRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyxcbiAgICAgICAgcGFwZXIgPSB7fSxcbiAgICAgICAgcHVzaCA9IFwicHVzaFwiLFxuICAgICAgICBJU1VSTCA9IFIuX0lTVVJMID0gL151cmxcXChbJ1wiXT8oLis/KVsnXCJdP1xcKSQvaSxcbiAgICAgICAgY29sb3VyUmVnRXhwID0gL15cXHMqKCgjW2EtZlxcZF17Nn0pfCgjW2EtZlxcZF17M30pfHJnYmE/XFwoXFxzKihbXFxkXFwuXSslP1xccyosXFxzKltcXGRcXC5dKyU/XFxzKixcXHMqW1xcZFxcLl0rJT8oPzpcXHMqLFxccypbXFxkXFwuXSslPyk/KVxccypcXCl8aHNiYT9cXChcXHMqKFtcXGRcXC5dKyg/OmRlZ3xcXHhiMHwlKT9cXHMqLFxccypbXFxkXFwuXSslP1xccyosXFxzKltcXGRcXC5dKyg/OiU/XFxzKixcXHMqW1xcZFxcLl0rKT8pJT9cXHMqXFwpfGhzbGE/XFwoXFxzKihbXFxkXFwuXSsoPzpkZWd8XFx4YjB8JSk/XFxzKixcXHMqW1xcZFxcLl0rJT9cXHMqLFxccypbXFxkXFwuXSsoPzolP1xccyosXFxzKltcXGRcXC5dKyk/KSU/XFxzKlxcKSlcXHMqJC9pLFxuICAgICAgICBpc25hbiA9IHtcIk5hTlwiOiAxLCBcIkluZmluaXR5XCI6IDEsIFwiLUluZmluaXR5XCI6IDF9LFxuICAgICAgICBiZXppZXJyZyA9IC9eKD86Y3ViaWMtKT9iZXppZXJcXCgoW14sXSspLChbXixdKyksKFteLF0rKSwoW15cXCldKylcXCkvLFxuICAgICAgICByb3VuZCA9IG1hdGgucm91bmQsXG4gICAgICAgIHNldEF0dHJpYnV0ZSA9IFwic2V0QXR0cmlidXRlXCIsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICB0b0ludCA9IHBhcnNlSW50LFxuICAgICAgICB1cHBlckNhc2UgPSBTdHIucHJvdG90eXBlLnRvVXBwZXJDYXNlLFxuICAgICAgICBhdmFpbGFibGVBdHRycyA9IFIuX2F2YWlsYWJsZUF0dHJzID0ge1xuICAgICAgICAgICAgXCJhcnJvdy1lbmRcIjogXCJub25lXCIsXG4gICAgICAgICAgICBcImFycm93LXN0YXJ0XCI6IFwibm9uZVwiLFxuICAgICAgICAgICAgYmx1cjogMCxcbiAgICAgICAgICAgIFwiY2xpcC1yZWN0XCI6IFwiMCAwIDFlOSAxZTlcIixcbiAgICAgICAgICAgIGN1cnNvcjogXCJkZWZhdWx0XCIsXG4gICAgICAgICAgICBjeDogMCxcbiAgICAgICAgICAgIGN5OiAwLFxuICAgICAgICAgICAgZmlsbDogXCIjZmZmXCIsXG4gICAgICAgICAgICBcImZpbGwtb3BhY2l0eVwiOiAxLFxuICAgICAgICAgICAgZm9udDogJzEwcHggXCJBcmlhbFwiJyxcbiAgICAgICAgICAgIFwiZm9udC1mYW1pbHlcIjogJ1wiQXJpYWxcIicsXG4gICAgICAgICAgICBcImZvbnQtc2l6ZVwiOiBcIjEwXCIsXG4gICAgICAgICAgICBcImZvbnQtc3R5bGVcIjogXCJub3JtYWxcIixcbiAgICAgICAgICAgIFwiZm9udC13ZWlnaHRcIjogNDAwLFxuICAgICAgICAgICAgZ3JhZGllbnQ6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgICAgICBocmVmOiBcImh0dHA6Ly9yYXBoYWVsanMuY29tL1wiLFxuICAgICAgICAgICAgXCJsZXR0ZXItc3BhY2luZ1wiOiAwLFxuICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgIHBhdGg6IFwiTTAsMFwiLFxuICAgICAgICAgICAgcjogMCxcbiAgICAgICAgICAgIHJ4OiAwLFxuICAgICAgICAgICAgcnk6IDAsXG4gICAgICAgICAgICBzcmM6IFwiXCIsXG4gICAgICAgICAgICBzdHJva2U6IFwiIzAwMFwiLFxuICAgICAgICAgICAgXCJzdHJva2UtZGFzaGFycmF5XCI6IFwiXCIsXG4gICAgICAgICAgICBcInN0cm9rZS1saW5lY2FwXCI6IFwiYnV0dFwiLFxuICAgICAgICAgICAgXCJzdHJva2UtbGluZWpvaW5cIjogXCJidXR0XCIsXG4gICAgICAgICAgICBcInN0cm9rZS1taXRlcmxpbWl0XCI6IDAsXG4gICAgICAgICAgICBcInN0cm9rZS1vcGFjaXR5XCI6IDEsXG4gICAgICAgICAgICBcInN0cm9rZS13aWR0aFwiOiAxLFxuICAgICAgICAgICAgdGFyZ2V0OiBcIl9ibGFua1wiLFxuICAgICAgICAgICAgXCJ0ZXh0LWFuY2hvclwiOiBcIm1pZGRsZVwiLFxuICAgICAgICAgICAgdGl0bGU6IFwiUmFwaGFlbFwiLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiBcIlwiLFxuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIFwiY2xhc3NcIjogXCJcIlxuICAgICAgICB9LFxuICAgICAgICBhdmFpbGFibGVBbmltQXR0cnMgPSBSLl9hdmFpbGFibGVBbmltQXR0cnMgPSB7XG4gICAgICAgICAgICBibHVyOiBudSxcbiAgICAgICAgICAgIFwiY2xpcC1yZWN0XCI6IFwiY3N2XCIsXG4gICAgICAgICAgICBjeDogbnUsXG4gICAgICAgICAgICBjeTogbnUsXG4gICAgICAgICAgICBmaWxsOiBcImNvbG91clwiLFxuICAgICAgICAgICAgXCJmaWxsLW9wYWNpdHlcIjogbnUsXG4gICAgICAgICAgICBcImZvbnQtc2l6ZVwiOiBudSxcbiAgICAgICAgICAgIGhlaWdodDogbnUsXG4gICAgICAgICAgICBvcGFjaXR5OiBudSxcbiAgICAgICAgICAgI
57590HBhdGg6IFwicGF0aFwiLFxuICAgICAgICAgICAgcjogbnUsXG4gICAgICAgICAgICByeDogbnUsXG4gICAgICAgICAgICByeTogbnUsXG4gICAgICAgICAgICBzdHJva2U6IFwiY29sb3VyXCIsXG4gICAgICAgICAgICBcInN0cm9rZS1vcGFjaXR5XCI6IG51LFxuICAgICAgICAgICAgXCJzdHJva2Utd2lkdGhcIjogbnUsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IFwidHJhbnNmb3JtXCIsXG4gICAgICAgICAgICB3aWR0aDogbnUsXG4gICAgICAgICAgICB4OiBudSxcbiAgICAgICAgICAgIHk6IG51XG4gICAgICAgIH0sXG4gICAgICAgIHdoaXRlc3BhY2UgPSAvW1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XS9nLFxuICAgICAgICBjb21tYVNwYWNlcyA9IC9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKixbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKi8sXG4gICAgICAgIGhzcmcgPSB7aHM6IDEsIHJnOiAxfSxcbiAgICAgICAgcDJzID0gLyw/KFthY2hsbXFyc3R2eHpdKSw/L2dpLFxuICAgICAgICBwYXRoQ29tbWFuZCA9IC8oW2FjaGxtcnFzdHZ6XSlbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjksXSooKC0/XFxkKlxcLj9cXGQqKD86ZVtcXC0rXT9cXGQrKT9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKiw/W1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XSopKykvaWcsXG4gICAgICAgIHRDb21tYW5kID0gLyhbcnN0bV0pW1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5LF0qKCgtP1xcZCpcXC4/XFxkKig/OmVbXFwtK10/XFxkKyk/W1xceDA5XFx4MGFcXHgwYlxceDBjXFx4MGRcXHgyMFxceGEwXFx1MTY4MFxcdTE4MGVcXHUyMDAwXFx1MjAwMVxcdTIwMDJcXHUyMDAzXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwYVxcdTIwMmZcXHUyMDVmXFx1MzAwMFxcdTIwMjhcXHUyMDI5XSosP1tcXHgwOVxceDBhXFx4MGJcXHgwY1xceDBkXFx4MjBcXHhhMFxcdTE2ODBcXHUxODBlXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMGFcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHUyMDI4XFx1MjAyOV0qKSspL2lnLFxuICAgICAgICBwYXRoVmFsdWVzID0gLygtP1xcZCpcXC4/XFxkKig/OmVbXFwtK10/XFxkKyk/KVtcXHgwOVxceDBhXFx4MGJcXHgwY1xceDBkXFx4MjBcXHhhMFxcdTE2ODBcXHUxODBlXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMGFcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHUyMDI4XFx1MjAyOV0qLD9bXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKi9pZyxcbiAgICAgICAgcmFkaWFsX2dyYWRpZW50ID0gUi5fcmFkaWFsX2dyYWRpZW50ID0gL15yKD86XFwoKFteLF0rPylbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKixbXFx4MDlcXHgwYVxceDBiXFx4MGNcXHgwZFxceDIwXFx4YTBcXHUxNjgwXFx1MTgwZVxcdTIwMDBcXHUyMDAxXFx1MjAwMlxcdTIwMDNcXHUyMDA0XFx1MjAwNVxcdTIwMDZcXHUyMDA3XFx1MjAwOFxcdTIwMDlcXHUyMDBhXFx1MjAyZlxcdTIwNWZcXHUzMDAwXFx1MjAyOFxcdTIwMjldKihbXlxcKV0rPylcXCkpPy8sXG4gICAgICAgIGVsZGF0YSA9IHt9LFxuICAgICAgICBzb3J0QnlLZXkgPSBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEua2V5IC0gYi5rZXk7XG4gICAgICAgIH0sXG4gICAgICAgIHNvcnRCeU51bWJlciA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gdG9GbG9hdChhKSAtIHRvRmxvYXQoYik7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1biA9IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgICBwaXBlID0gZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgI
57590HJldHVybiB4O1xuICAgICAgICB9LFxuICAgICAgICByZWN0UGF0aCA9IFIuX3JlY3RQYXRoID0gZnVuY3Rpb24gKHgsIHksIHcsIGgsIHIpIHtcbiAgICAgICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtbXCJNXCIsIHggKyByLCB5XSwgW1wibFwiLCB3IC0gciAqIDIsIDBdLCBbXCJhXCIsIHIsIHIsIDAsIDAsIDEsIHIsIHJdLCBbXCJsXCIsIDAsIGggLSByICogMl0sIFtcImFcIiwgciwgciwgMCwgMCwgMSwgLXIsIHJdLCBbXCJsXCIsIHIgKiAyIC0gdywgMF0sIFtcImFcIiwgciwgciwgMCwgMCwgMSwgLXIsIC1yXSwgW1wibFwiLCAwLCByICogMiAtIGhdLCBbXCJhXCIsIHIsIHIsIDAsIDAsIDEsIHIsIC1yXSwgW1wielwiXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW1tcIk1cIiwgeCwgeV0sIFtcImxcIiwgdywgMF0sIFtcImxcIiwgMCwgaF0sIFtcImxcIiwgLXcsIDBdLCBbXCJ6XCJdXTtcbiAgICAgICAgfSxcbiAgICAgICAgZWxsaXBzZVBhdGggPSBmdW5jdGlvbiAoeCwgeSwgcngsIHJ5KSB7XG4gICAgICAgICAgICBpZiAocnkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJ5ID0gcng7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW1tcIk1cIiwgeCwgeV0sIFtcIm1cIiwgMCwgLXJ5XSwgW1wiYVwiLCByeCwgcnksIDAsIDEsIDEsIDAsIDIgKiByeV0sIFtcImFcIiwgcngsIHJ5LCAwLCAxLCAxLCAwLCAtMiAqIHJ5XSwgW1wielwiXV07XG4gICAgICAgIH0sXG4gICAgICAgIGdldFBhdGggPSBSLl9nZXRQYXRoID0ge1xuICAgICAgICAgICAgcGF0aDogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsLmF0dHIoXCJwYXRoXCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNpcmNsZTogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGEgPSBlbC5hdHRycztcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxsaXBzZVBhdGgoYS5jeCwgYS5jeSwgYS5yKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbGxpcHNlOiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgYSA9IGVsLmF0dHJzO1xuICAgICAgICAgICAgICAgIHJldHVybiBlbGxpcHNlUGF0aChhLmN4LCBhLmN5LCBhLnJ4LCBhLnJ5KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZWN0OiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgYSA9IGVsLmF0dHJzO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChhLngsIGEueSwgYS53aWR0aCwgYS5oZWlnaHQsIGEucik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW1hZ2U6IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgIHZhciBhID0gZWwuYXR0cnM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlY3RQYXRoKGEueCwgYS55LCBhLndpZHRoLCBhLmhlaWdodCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGV4dDogZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJib3ggPSBlbC5fZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChiYm94LngsIGJib3gueSwgYmJveC53aWR0aCwgYmJveC5oZWlnaHQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCA6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJib3ggPSBlbC5fZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWN0UGF0aChiYm94LngsIGJib3gueSwgYmJveC53aWR0aCwgYmJveC5oZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwubWFwUGF0aFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVHJhbnNmb3JtIHRoZSBwYXRoIHN0cmluZyB3aXRoIGdpdmVuIG1hdHJpeC5cbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBwYXRoIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgICAgICAtIG1hdHJpeCAob2JqZWN0KSBzZWUgQE1hdHJpeFxuICAgICAgICAgPSAoc3RyaW5nKSB0cmFuc2Zvcm1lZCBwYXRoIHN0cmluZ1xuICAgICAgICBcXCovXG4gICAgICAgIG1hcFBhdGggPSBSLm1hcFBhdGggPSBmdW5jdGlvbiAocGF0aCwgbWF0cml4KSB7XG4gICAgICAgICAgICBpZiAoIW1hdHJpeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHgsIHksIGksIGosIGlpLCBqaiwgcGF0aGk7XG4gICAgICAgICAgICBwYXRoID0gcGF0aDJjdXJ2ZShwYXRoKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gcGF0aC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGF0aGkgPSBwYXRoW2ldO1xuICAgICAgICAgICAgICAgIGZvciAoaiA9IDEsIGpqID0gcGF0aGkubGVuZ3RoOyBqIDwgamo7IGogKz0gMikge1xuICAgICAgICAgICAgICAgICAgICB4ID0gbWF0cml4LngocGF0aGlbal0sIHBhdGhpW2ogKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgIHkgPSBtYXRyaXgueShwYXRoaVtqXSwgcGF0aGlbaiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aGlbal0gPSB4O1xuICAgICAgICAgICAgICAgICAgICBwYXRoaVtqICsgMV0gPSB5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgICB9O1xuXG4gICAgUi5fZyA9IGc7XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwudHlwZVxuICAgICBbIHByb3BlcnR5IChzdHJpbmcpIF1cbiAgICAgKipcbiAgICAgKiBDYW4gYmUg4oCcU1ZH4oCdLCDigJxWTUzigJ0gb3IgZW1wdHksIGRlcGVuZGluZyBvbiBicm93c2VyIHN1cHBvcnQuXG4gICAgXFwqL1xuICAgIFIudHlwZSA9IChnLndpbi5TVkdBbmdsZSB8fCBnLmRvYy5pbXBsZW1lbnRhdGlvbi5oYXNGZWF0dXJlKFwiaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNCYXNpY1N0cnVjdHVyZVwiLCBcIjEuMVwiKSA/IFwiU1ZHXCIgOiBcIlZNTFwiKTtcbiAgICBpZiAoUi50eXBlID09IFwiVk1MXCIpIHtcbiAgICAgICAgdmFyIGQgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgYjtcbiAgICAgICAgZC5pbm5lckhUTUwgPSAnPHY6c2hhcGUgYWRqPVwiMVwiLz4nO1xuICAgICAgICBiID0gZC5maXJzdENoaWxkO1xuICAgICAgICBiLnN0eWxlLmJlaGF2aW9yID0gXCJ1cmwoI2RlZmF1bHQjVk1MKVwiO1xuICAgICAgICBpZiAoIShiICYmIHR5cGVvZiBiLmFkaiA9PSBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIChSLnR5cGUgPSBFKTtcbiAgICAgICAgfVxuICAgICAgICBkID0gbnVsbDtcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuc3ZnXG4gICAgIFsgcHJvcGVydHkgKGJvb2xlYW4pIF1cbiAgICAgKipcbiAgICAgKiBgdHJ1ZWAgaWYgYnJvd3NlciBzdXBwb3J0cyBTVkcuXG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnZtbFxuICAgICBbIHByb3BlcnR5IChib29sZWFuKSBdXG4gICAgICoqXG4gICAgICogYHRydWVgIGlmIGJyb3dzZXIgc3VwcG9ydHMgVk1MLlxuICAgIFxcKi9cbiAgICBSLnN2ZyA9ICEoUi52bWwgPSBSLnR5cGUgPT0gXCJWTUxcIik7XG4gICAgUi5fUGFwZXIgPSBQYXBlcjtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mblxuICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgKipcbiAgICAgKiBZb3UgY2FuIGFkZCB5b3VyIG93biBtZXRob2QgdG8gdGhlIGNhbnZhcy4gRm9yIGV4YW1wbGUgaWYgeW91IHdhbnQgdG8gZHJhdyBhIHBpZSBjaGFydCxcbiAgICAgKiB5b3UgY2FuIGNyZWF0ZSB5b3VyIG93biBwaWUgY2hhcnQgZnVuY3Rpb24gYW5kIHNoaXAgaXQgYXMgYSBSYXBoYcOrbCBwbHVnaW4uIFRvIGRvIHRoaXNcbiAgICAgKiB5b3UgbmVlZCB0byBleHRlbmQgdGhlIGBSYXBoYWVsLmZuYCBvYmplY3QuIFlvdSBzaG91bGQgbW9kaWZ5IHRoZSBgZm5gIG9iamVjdCBiZWZvcmUgYVxuICAgICAqIFJhcGhhw6tsIGluc3RhbmNlIGlzIGNyZWF0ZWQsIG90aGVyd2lzZSBpdCB3aWxsIHRha2Ugbm8gZWZmZWN0LiBQbGVhc2Ugbm90ZSB0aGF0IHR
57590oZVxuICAgICAqIGFiaWxpdHkgZm9yIG5hbWVzcGFjZWQgcGx1Z2lucyB3YXMgcmVtb3ZlZCBpbiBSYXBoYWVsIDIuMC4gSXQgaXMgdXAgdG8gdGhlIHBsdWdpbiB0b1xuICAgICAqIGVuc3VyZSBhbnkgbmFtZXNwYWNpbmcgZW5zdXJlcyBwcm9wZXIgY29udGV4dC5cbiAgICAgPiBVc2FnZVxuICAgICB8IFJhcGhhZWwuZm4uYXJyb3cgPSBmdW5jdGlvbiAoeDEsIHkxLCB4MiwgeTIsIHNpemUpIHtcbiAgICAgfCAgICAgcmV0dXJuIHRoaXMucGF0aCggLi4uICk7XG4gICAgIHwgfTtcbiAgICAgfCAvLyBvciBjcmVhdGUgbmFtZXNwYWNlXG4gICAgIHwgUmFwaGFlbC5mbi5teXN0dWZmID0ge1xuICAgICB8ICAgICBhcnJvdzogZnVuY3Rpb24gKCkge+KApn0sXG4gICAgIHwgICAgIHN0YXI6IGZ1bmN0aW9uICgpIHvigKZ9LFxuICAgICB8ICAgICAvLyBldGPigKZcbiAgICAgfCB9O1xuICAgICB8IHZhciBwYXBlciA9IFJhcGhhZWwoMTAsIDEwLCA2MzAsIDQ4MCk7XG4gICAgIHwgLy8gdGhlbiB1c2UgaXRcbiAgICAgfCBwYXBlci5hcnJvdygxMCwgMTAsIDMwLCAzMCwgNSkuYXR0cih7ZmlsbDogXCIjZjAwXCJ9KTtcbiAgICAgfCBwYXBlci5teXN0dWZmLmFycm93KCk7XG4gICAgIHwgcGFwZXIubXlzdHVmZi5zdGFyKCk7XG4gICAgXFwqL1xuICAgIFIuZm4gPSBwYXBlcnByb3RvID0gUGFwZXIucHJvdG90eXBlID0gUi5wcm90b3R5cGU7XG4gICAgUi5faWQgPSAwO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmlzXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBIYW5kZnVsIG9mIHJlcGxhY2VtZW50cyBmb3IgYHR5cGVvZmAgb3BlcmF0b3IuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIG8gKOKApikgYW55IG9iamVjdCBvciBwcmltaXRpdmVcbiAgICAgLSB0eXBlIChzdHJpbmcpIG5hbWUgb2YgdGhlIHR5cGUsIGkuZS4g4oCcc3RyaW5n4oCdLCDigJxmdW5jdGlvbuKAnSwg4oCcbnVtYmVy4oCdLCBldGMuXG4gICAgID0gKGJvb2xlYW4pIGlzIGdpdmVuIHZhbHVlIGlzIG9mIGdpdmVuIHR5cGVcbiAgICBcXCovXG4gICAgUi5pcyA9IGZ1bmN0aW9uIChvLCB0eXBlKSB7XG4gICAgICAgIHR5cGUgPSBsb3dlckNhc2UuY2FsbCh0eXBlKTtcbiAgICAgICAgaWYgKHR5cGUgPT0gXCJmaW5pdGVcIikge1xuICAgICAgICAgICAgcmV0dXJuICFpc25hbltoYXNdKCtvKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PSBcImFycmF5XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBvIGluc3RhbmNlb2YgQXJyYXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICAodHlwZSA9PSBcIm51bGxcIiAmJiBvID09PSBudWxsKSB8fFxuICAgICAgICAgICAgICAgICh0eXBlID09IHR5cGVvZiBvICYmIG8gIT09IG51bGwpIHx8XG4gICAgICAgICAgICAgICAgKHR5cGUgPT0gXCJvYmplY3RcIiAmJiBvID09PSBPYmplY3QobykpIHx8XG4gICAgICAgICAgICAgICAgKHR5cGUgPT0gXCJhcnJheVwiICYmIEFycmF5LmlzQXJyYXkgJiYgQXJyYXkuaXNBcnJheShvKSkgfHxcbiAgICAgICAgICAgICAgICBvYmplY3RUb1N0cmluZy5jYWxsKG8pLnNsaWNlKDgsIC0xKS50b0xvd2VyQ2FzZSgpID09IHR5cGU7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGNsb25lKG9iaikge1xuICAgICAgICBpZiAodHlwZW9mIG9iaiA9PSBcImZ1bmN0aW9uXCIgfHwgT2JqZWN0KG9iaikgIT09IG9iaikge1xuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgcmVzID0gbmV3IG9iai5jb25zdHJ1Y3RvcjtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKG9ialtoYXNdKGtleSkpIHtcbiAgICAgICAgICAgIHJlc1trZXldID0gY2xvbmUob2JqW2tleV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuYW5nbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgYW5nbGUgYmV0d2VlbiB0d28gb3IgdGhyZWUgcG9pbnRzXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHgxIChudW1iZXIpIHggY29vcmQgb2YgZmlyc3QgcG9pbnRcbiAgICAgLSB5MSAobnVtYmVyKSB5IGNvb3JkIG9mIGZpcnN0IHBvaW50XG4gICAgIC0geDIgKG51bWJlcikgeCBjb29yZCBvZiBzZWNvbmQgcG9pbnRcbiAgICAgLSB5MiAobnVtYmVyKSB5IGNvb3JkIG9mIHNlY29uZCBwb2ludFxuICAgICAtIHgzIChudW1iZXIpICNvcHRpb25hbCB4IGNvb3JkIG9mIHRoaXJkIHBvaW50XG4gICAgIC0geTMgKG51bWJlcikgI29wdGlvbmFsIHkgY29vcmQgb2YgdGhpcmQgcG9pbnRcbiAgICAgPSAobnVtYmVyKSBhbmdsZSBpbiBkZWdyZWVzLlxuICAgIFxcKi9cbiAgICBSLmFuZ2xlID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpIHtcbiAgICAgICAgaWYgKHgzID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciB4ID0geDEgLSB4MixcbiAgICAgICAgICAgICAgICB5ID0geTEgLSB5MjtcbiAgICAgICAgICAgIGlmICgheCAmJiAheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICgxODAgKyBtYXRoLmF0YW4yKC15LCAteCkgKiAxODAgLyBQSSArIDM2MCkgJSAzNjA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUi5hbmdsZSh4MSwgeTEsIHgzLCB5MykgLSBSLmFuZ2xlKHgyLCB5MiwgeDMsIHkzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucmFkXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBUcmFuc2Zvcm0gYW5nbGUgdG8gcmFkaWFuc1xuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBkZWcgKG51bWJlcikgYW5nbGUgaW4gZGVncmVlc1xuICAgICA9IChudW1iZXIpIGFuZ2xlIGluIHJhZGlhbnMuXG4gICAgXFwqL1xuICAgIFIucmFkID0gZnVuY3Rpb24gKGRlZykge1xuICAgICAgICByZXR1cm4gZGVnICUgMzYwICogUEkgLyAxODA7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5kZWdcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFRyYW5zZm9ybSBhbmdsZSB0byBkZWdyZWVzXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHJhZCAobnVtYmVyKSBhbmdsZSBpbiByYWRpYW5zXG4gICAgID0gKG51bWJlcikgYW5nbGUgaW4gZGVncmVlcy5cbiAgICBcXCovXG4gICAgUi5kZWcgPSBmdW5jdGlvbiAocmFkKSB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kICgocmFkICogMTgwIC8gUEklIDM2MCkqIDEwMDApIC8gMTAwMDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnNuYXBUb1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogU25hcHMgZ2l2ZW4gdmFsdWUgdG8gZ2l2ZW4gZ3JpZC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gdmFsdWVzIChhcnJheXxudW1iZXIpIGdpdmVuIGFycmF5IG9mIHZhbHVlcyBvciBzdGVwIG9mIHRoZSBncmlkXG4gICAgIC0gdmFsdWUgKG51bWJlcikgdmFsdWUgdG8gYWRqdXN0XG4gICAgIC0gdG9sZXJhbmNlIChudW1iZXIpICNvcHRpb25hbCB0b2xlcmFuY2UgZm9yIHNuYXBwaW5nLiBEZWZhdWx0IGlzIGAxMGAuXG4gICAgID0gKG51bWJlcikgYWRqdXN0ZWQgdmFsdWUuXG4gICAgXFwqL1xuICAgIFIuc25hcFRvID0gZnVuY3Rpb24gKHZhbHVlcywgdmFsdWUsIHRvbGVyYW5jZSkge1xuICAgICAgICB0b2xlcmFuY2UgPSBSLmlzKHRvbGVyYW5jZSwgXCJmaW5pdGVcIikgPyB0b2xlcmFuY2UgOiAxMDtcbiAgICAgICAgaWYgKFIuaXModmFsdWVzLCBhcnJheSkpIHtcbiAgICAgICAgICAgIHZhciBpID0gdmFsdWVzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIGlmIChhYnModmFsdWVzW2ldIC0gdmFsdWUpIDw9IHRvbGVyYW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZXMgPSArdmFsdWVzO1xuICAgICAgICAgICAgdmFyIHJlbSA9IHZhbHVlICUgdmFsdWVzO1xuICAgICAgICAgICAgaWYgKHJlbSA8IHRvbGVyYW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZSAtIHJlbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyZW0gPiB2YWx1ZXMgLSB0b2xlcmFuY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUgLSByZW0gKyB2YWx1ZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5jcmVhdGVVVUlEXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIFJGQzQxMjIsIHZlcnNpb24gNCBJRFxuICAgIFxcKi9cbiAgICB2YXIgY3JlYXRlVVVJRCA9IFIuY3JlYXRlVVVJRCA9IChmdW5jdGlvbiAodXVpZFJlZ0V4LCB1dWlkUmVwbGFjZXIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcInh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eFwiLnJlcGxhY2UodXVpZFJlZ0V4LCB1dWlkUmVwbGFjZXIpLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgIH07XG4gICAgfSkoL1t4eV0vZywgZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgdmFyIHIgPSBtYXRoLnJhbmRvbSgpICogMTYgfCAwLFxuICAgICAgICAgICAgdiA9IGMgPT0gXCJ4XCIgPyByIDogKHIgJiAzIHwgOCk7XG4gICAgICAgIHJldHVybiB2LnRvU3RyaW5nKDE2KTtcbiAgICB9KTtcblxuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnNldFdpbmRvd1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXNlZCB3aGVuIHlvdSBuZWVkIHRvIGRyYXcgaW4gYCZsdDtpZnJhbWU+YC4gU3dpdGNoZWQgd2luZG93IHRvIHRoZSBpZnJhbWUgb25lLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBuZXd3aW4gKHdpbmRvdykgbmV3IHdpbmRvdyBvYmplY3RcbiAgICBcXCovXG4gICAgUi5zZXRXaW5kb3cgPSBmdW5jdGlvbiAobmV3d2luKSB7XG4gICAgICAgIGV2ZShcInJhcGhhZWwuc2V0V2luZG93XCIsIFIsIGcud2luLCBuZXd3aW4pO1xuICAgICAgICBnLndpbiA9IG5ld3dpbjtcbiAgICAgICAgZy5kb2MgPSBnLndpbi5kb2N1bWVudDtcbiAgICAgICAgaWYgKFIuX2VuZ2luZS5pbml0V2luKSB7XG4gICAgICAgICAgICBSLl9lbmdpbmUuaW5pdFdpbihnLndpbik7XG4gICAgICAgI
57590H1cbiAgICB9O1xuICAgIHZhciB0b0hleCA9IGZ1bmN0aW9uIChjb2xvcikge1xuICAgICAgICBpZiAoUi52bWwpIHtcbiAgICAgICAgICAgIC8vIGh0dHA6Ly9kZWFuLmVkd2FyZHMubmFtZS93ZWJsb2cvMjAwOS8xMC9jb252ZXJ0LWFueS1jb2xvdXItdmFsdWUtdG8taGV4LWluLW1zaWUvXG4gICAgICAgICAgICB2YXIgdHJpbSA9IC9eXFxzK3xcXHMrJC9nO1xuICAgICAgICAgICAgdmFyIGJvZDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvY3VtID0gbmV3IEFjdGl2ZVhPYmplY3QoXCJodG1sZmlsZVwiKTtcbiAgICAgICAgICAgICAgICBkb2N1bS53cml0ZShcIjxib2R5PlwiKTtcbiAgICAgICAgICAgICAgICBkb2N1bS5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIGJvZCA9IGRvY3VtLmJvZHk7XG4gICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgICBib2QgPSBjcmVhdGVQb3B1cCgpLmRvY3VtZW50LmJvZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmFuZ2UgPSBib2QuY3JlYXRlVGV4dFJhbmdlKCk7XG4gICAgICAgICAgICB0b0hleCA9IGNhY2hlcihmdW5jdGlvbiAoY29sb3IpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBib2Quc3R5bGUuY29sb3IgPSBTdHIoY29sb3IpLnJlcGxhY2UodHJpbSwgRSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHJhbmdlLnF1ZXJ5Q29tbWFuZFZhbHVlKFwiRm9yZUNvbG9yXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9ICgodmFsdWUgJiAyNTUpIDw8IDE2KSB8ICh2YWx1ZSAmIDY1MjgwKSB8ICgodmFsdWUgJiAxNjcxMTY4MCkgPj4+IDE2KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiI1wiICsgKFwiMDAwMDAwXCIgKyB2YWx1ZS50b1N0cmluZygxNikpLnNsaWNlKC02KTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibm9uZVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGkgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiaVwiKTtcbiAgICAgICAgICAgIGkudGl0bGUgPSBcIlJhcGhhXFx4ZWJsIENvbG91ciBQaWNrZXJcIjtcbiAgICAgICAgICAgIGkuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgZy5kb2MuYm9keS5hcHBlbmRDaGlsZChpKTtcbiAgICAgICAgICAgIHRvSGV4ID0gY2FjaGVyKGZ1bmN0aW9uIChjb2xvcikge1xuICAgICAgICAgICAgICAgIGkuc3R5bGUuY29sb3IgPSBjb2xvcjtcbiAgICAgICAgICAgICAgICByZXR1cm4gZy5kb2MuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShpLCBFKS5nZXRQcm9wZXJ0eVZhbHVlKFwiY29sb3JcIik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9IZXgoY29sb3IpO1xuICAgIH0sXG4gICAgaHNidG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcImhzYihcIiArIFt0aGlzLmgsIHRoaXMucywgdGhpcy5iXSArIFwiKVwiO1xuICAgIH0sXG4gICAgaHNsdG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcImhzbChcIiArIFt0aGlzLmgsIHRoaXMucywgdGhpcy5sXSArIFwiKVwiO1xuICAgIH0sXG4gICAgcmdidG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhleDtcbiAgICB9LFxuICAgIHByZXBhcmVSR0IgPSBmdW5jdGlvbiAociwgZywgYikge1xuICAgICAgICBpZiAoZyA9PSBudWxsICYmIFIuaXMociwgXCJvYmplY3RcIikgJiYgXCJyXCIgaW4gciAmJiBcImdcIiBpbiByICYmIFwiYlwiIGluIHIpIHtcbiAgICAgICAgICAgIGIgPSByLmI7XG4gICAgICAgICAgICBnID0gci5nO1xuICAgICAgICAgICAgciA9IHIucjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZyA9PSBudWxsICYmIFIuaXMociwgc3RyaW5nKSkge1xuICAgICAgICAgICAgdmFyIGNsciA9IFIuZ2V0UkdCKHIpO1xuICAgICAgICAgICAgciA9IGNsci5yO1xuICAgICAgICAgICAgZyA9IGNsci5nO1xuICAgICAgICAgICAgYiA9IGNsci5iO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyID4gMSB8fCBnID4gMSB8fCBiID4gMSkge1xuICAgICAgICAgICAgciAvPSAyNTU7XG4gICAgICAgICAgICBnIC89IDI1NTtcbiAgICAgICAgICAgIGIgLz0gMjU1O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtyLCBnLCBiXTtcbiAgICB9LFxuICAgIHBhY2thZ2VSR0IgPSBmdW5jdGlvbiAociwgZywgYiwgbykge1xuICAgICAgICByICo9IDI1NTtcbiAgICAgICAgZyAqPSAyNTU7XG4gICAgICAgIGIgKj0gMjU1O1xuICAgICAgICB2Y
57590XIgcmdiID0ge1xuICAgICAgICAgICAgcjogcixcbiAgICAgICAgICAgIGc6IGcsXG4gICAgICAgICAgICBiOiBiLFxuICAgICAgICAgICAgaGV4OiBSLnJnYihyLCBnLCBiKSxcbiAgICAgICAgICAgIHRvU3RyaW5nOiByZ2J0b1N0cmluZ1xuICAgICAgICB9O1xuICAgICAgICBSLmlzKG8sIFwiZmluaXRlXCIpICYmIChyZ2Iub3BhY2l0eSA9IG8pO1xuICAgICAgICByZXR1cm4gcmdiO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5jb2xvclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUGFyc2VzIHRoZSBjb2xvciBzdHJpbmcgYW5kIHJldHVybnMgb2JqZWN0IHdpdGggYWxsIHZhbHVlcyBmb3IgdGhlIGdpdmVuIGNvbG9yLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBjbHIgKHN0cmluZykgY29sb3Igc3RyaW5nIGluIG9uZSBvZiB0aGUgc3VwcG9ydGVkIGZvcm1hdHMgKHNlZSBAUmFwaGFlbC5nZXRSR0IpXG4gICAgID0gKG9iamVjdCkgQ29tYmluZWQgUkdCICYgSFNCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlLFxuICAgICBvICAgICBoZXggKHN0cmluZykgY29sb3IgaW4gSFRNTC9DU1MgZm9ybWF0OiAj4oCi4oCi4oCi4oCi4oCi4oCiLFxuICAgICBvICAgICBlcnJvciAoYm9vbGVhbikgYHRydWVgIGlmIHN0cmluZyBjYW7igJl0IGJlIHBhcnNlZCxcbiAgICAgbyAgICAgaCAobnVtYmVyKSBodWUsXG4gICAgIG8gICAgIHMgKG51bWJlcikgc2F0dXJhdGlvbixcbiAgICAgbyAgICAgdiAobnVtYmVyKSB2YWx1ZSAoYnJpZ2h0bmVzcyksXG4gICAgIG8gICAgIGwgKG51bWJlcikgbGlnaHRuZXNzXG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmNvbG9yID0gZnVuY3Rpb24gKGNscikge1xuICAgICAgICB2Y
57590XIgcmdiO1xuICAgICAgICBpZiAoUi5pcyhjbHIsIFwib2JqZWN0XCIpICYmIFwiaFwiIGluIGNsciAmJiBcInNcIiBpbiBjbHIgJiYgXCJiXCIgaW4gY2xyKSB7XG4gICAgICAgICAgICByZ2IgPSBSLmhzYjJyZ2IoY2xyKTtcbiAgICAgICAgICAgIGNsci5yID0gcmdiLnI7XG4gICAgICAgICAgICBjbHIuZyA9IHJnYi5nO1xuICAgICAgICAgICAgY2xyLmIgPSByZ2IuYjtcbiAgICAgICAgICAgIGNsci5oZXggPSByZ2IuaGV4O1xuICAgICAgICB9IGVsc2UgaWYgKFIuaXMoY2xyLCBcIm9iamVjdFwiKSAmJiBcImhcIiBpbiBjbHIgJiYgXCJzXCIgaW4gY2xyICYmIFwibFwiIGluIGNscikge1xuICAgICAgICAgICAgcmdiID0gUi5oc2wycmdiKGNscik7XG4gICAgICAgICAgICBjbHIuciA9IHJnYi5yO1xuICAgICAgICAgICAgY2xyLmcgPSByZ2IuZztcbiAgICAgICAgICAgIGNsci5iID0gcmdiLmI7XG4gICAgICAgICAgICBjbHIuaGV4ID0gcmdiLmhleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChSLmlzKGNsciwgXCJzdHJpbmdcIikpIHtcbiAgICAgICAgICAgICAgICBjbHIgPSBSLmdldFJHQihjbHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFIuaXMoY2xyLCBcIm9iamVjdFwiKSAmJiBcInJcIiBpbiBjbHIgJiYgXCJnXCIgaW4gY2xyICYmIFwiYlwiIGluIGNscikge1xuICAgICAgICAgICAgICAgIHJnYiA9IFIucmdiMmhzbChjbHIpO1xuICAgICAgICAgICAgICAgIGNsci5oID0gcmdiLmg7XG4gICAgICAgICAgICAgICAgY2xyLnMgPSByZ2IucztcbiAgICAgICAgICAgICAgICBjbHIubCA9IHJnYi5sO1xuICAgICAgICAgICAgICAgIHJnYiA9IFIucmdiMmhzYihjbHIpO1xuICAgICAgICAgICAgICAgIGNsci52ID0gcmdiLmI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNsciA9IHtoZXg6IFwibm9uZVwifTtcbiAgICAgICAgICAgICAgICBjbHIuciA9IGNsci5nID0gY2xyLmIgPSBjbHIuaCA9IGNsci5zID0gY2xyLnYgPSBjbHIubCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNsci50b1N0cmluZyA9IHJnYnRvU3RyaW5nO1xuICAgICAgICByZXR1cm4gY2xyO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuaHNiMnJnYlxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgSFNCIHZhbHVlcyB0byBSR0Igb2JqZWN0LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoIChudW1iZXIpIGh1ZVxuICAgICAtIHMgKG51bWJlcikgc2F0dXJhdGlvblxuICAgICAtIHYgKG51bWJlcikgdmFsdWUgb3IgYnJpZ2h0bmVzc1xuICAgICA9IChvYmplY3QpIFJHQiBvYmplY3QgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgciAobnVtYmVyKSByZWQsXG4gICAgIG8gICAgIGcgKG51bWJlcikgZ3JlZW4sXG4gICAgIG8gICAgIGIgKG51bWJlcikgYmx1ZSxcbiAgICAgbyAgICAgaGV4IChzdHJpbmcpIGNvbG9yIGluIEhUTUwvQ1NTIGZvcm1hdDogI+KAouKAouKAouKAouKAouKAolxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5oc2IycmdiID0gZnVuY3Rpb24gKGgsIHMsIHYsIG8pIHtcbiAgICAgICAgaWYgKHRoaXMuaXMoaCwgXCJvYmplY3RcIikgJiYgXCJoXCIgaW4gaCAmJiBcInNcIiBpbiBoICYmIFwiYlwiIGluIGgpIHtcbiAgICAgICAgICAgIHYgPSBoLmI7XG4gICAgICAgICAgICBzID0gaC5zO1xuICAgICAgICAgICAgbyA9IGgubztcbiAgICAgICAgICAgIGggPSBoLmg7XG4gICAgICAgIH1cbiAgICAgICAgaCAqPSAzNjA7XG4gICAgICAgIHZhciBSLCBHLCBCLCBYLCBDO1xuICAgICAgICBoID0gKGggJSAzNjApIC8gNjA7XG4gICAgICAgIEMgPSB2ICogcztcbiAgICAgICAgWCA9IEMgKiAoMSAtIGFicyhoICUgMiAtIDEpKTtcbiAgICAgICAgUiA9IEcgPSBCID0gdiAtIEM7XG5cbiAgICAgICAgaCA9IH5+aDtcbiAgICAgICAgUiArPSBbQywgWCwgMCwgMCwgWCwgQ11baF07XG4gICAgICAgIEcgKz0gW1gsIEMsIEMsIFgsIDAsIDBdW2hdO1xuICAgICAgICBCICs9IFswLCAwLCBYLCBDLCBDLCBYXVtoXTtcbiAgICAgICAgcmV0dXJuIHBhY2thZ2VSR0IoUiwgRywgQiwgbyk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5oc2wycmdiXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBIU0wgdmFsdWVzIHRvIFJHQiBvYmplY3QuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGggKG51bWJlcikgaHVlXG4gICAgIC0gcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIC0gbCAobnVtYmVyKSBsdW1pbm9zaXR5XG4gICAgID0gKG9iamVjdCkgUkdCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlLFxuICAgICBvICAgICBoZXggKHN0cmluZykgY29sb3IgaW4gSFRNTC9DU1MgZm9ybWF0OiAj4oCi4oCi4oCi4oCi4oCi4oCiXG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmhzbDJyZ2IgPSBmdW5jdGlvbiAoaCwgcywgbCwgbykge1xuICAgICAgICBpZiAodGhpcy5pcyhoLCBcIm9iamVjdFwiKSAmJiBcImhcIiBpbiBoICYmIFwic1wiIGluIGggJiYgXCJsXCIgaW4gaCkge1xuICAgICAgICAgICAgbCA9IGgubDtcbiAgICAgICAgICAgIHMgPSBoLnM7XG4gICAgICAgICAgICBoID0gaC5oO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoID4gMSB8fCBzID4gMSB8fCBsID4gMSkge1xuICAgICAgICAgICAgaCAvPSAzNjA7XG4gICAgICAgICAgICBzIC89IDEwMDtcbiAgICAgICAgICAgIGwgLz0gMTAwO1xuICAgICAgICB9XG4gICAgICAgIGggKj0gMzYwO1xuICAgICAgICB2Y
57590XIgUiwgRywgQiwgWCwgQztcbiAgICAgICAgaCA9IChoICUgMzYwKSAvIDYwO1xuICAgICAgICBDID0gMiAqIHMgKiAobCA8IC41ID8gbCA6IDEgLSBsKTtcbiAgICAgICAgWCA9IEMgKiAoMSAtIGFicyhoICUgMiAtIDEpKTtcbiAgICAgICAgUiA9IEcgPSBCID0gbCAtIEMgLyAyO1xuXG4gICAgICAgIGggPSB+fmg7XG4gICAgICAgIFIgKz0gW0MsIFgsIDAsIDAsIFgsIENdW2hdO1xuICAgICAgICBHICs9IFtYLCBDLCBDLCBYLCAwLCAwXVtoXTtcbiAgICAgICAgQiArPSBbMCwgMCwgWCwgQywgQywgWF1baF07XG4gICAgICAgIHJldHVybiBwYWNrYWdlUkdCKFIsIEcsIEIsIG8pO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucmdiMmhzYlxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgUkdCIHZhbHVlcyB0byBIU0Igb2JqZWN0LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSByIChudW1iZXIpIHJlZFxuICAgICAtIGcgKG51bWJlcikgZ3JlZW5cbiAgICAgLSBiIChudW1iZXIpIGJsdWVcbiAgICAgPSAob2JqZWN0KSBIU0Igb2JqZWN0IGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIGggKG51bWJlcikgaHVlXG4gICAgIG8gICAgIHMgKG51bWJlcikgc2F0dXJhdGlvblxuICAgICBvICAgICBiIChudW1iZXIpIGJyaWdodG5lc3NcbiAgICAgbyB9XG4gICAgXFwqL1xuICAgIFIucmdiMmhzYiA9IGZ1bmN0aW9uIChyLCBnLCBiKSB7XG4gICAgICAgIGIgPSBwcmVwYXJlUkdCKHIsIGcsIGIpO1xuICAgICAgICByID0gYlswXTtcbiAgICAgICAgZyA9IGJbMV07XG4gICAgICAgIGIgPSBiWzJdO1xuXG4gICAgICAgIHZhciBILCBTLCBWLCBDO1xuICAgICAgICBWID0gbW1heChyLCBnLCBiKTtcbiAgICAgICAgQyA9IFYgLSBtbWluKHIsIGcsIGIpO1xuICAgICAgICBIID0gKEMgPT0gMCA/IG51bGwgOlxuICAgICAgICAgICAgIFYgPT0gciA/IChnIC0gYikgLyBDIDpcbiAgICAgICAgICAgICBWID09IGcgPyAoYiAtIHIpIC8gQyArIDIgOlxuICAgICAgICAgICAgICAgICAgICAgIChyIC0gZykgLyBDICsgNFxuICAgICAgICAgICAgKTtcbiAgICAgICAgSCA9ICgoSCArIDM2MCkgJSA2KSAqIDYwIC8gMzYwO1xuICAgICAgICBTID0gQyA9PSAwID8gMCA6IEMgLyBWO1xuICAgICAgICByZXR1cm4ge2g6IEgsIHM6IFMsIGI6IFYsIHRvU3RyaW5nOiBoc2J0b1N0cmluZ307XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5yZ2IyaHNsXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBSR0IgdmFsdWVzIHRvIEhTTCBvYmplY3QuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHIgKG51bWJlcikgcmVkXG4gICAgIC0gZyAobnVtYmVyKSBncmVlblxuICAgICAtIGIgKG51bWJlcikgYmx1ZVxuICAgICA9IChvYmplY3QpIEhTTCBvYmplY3QgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgaCAobnVtYmVyKSBodWVcbiAgICAgbyAgICAgcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIG8gICAgIGwgKG51bWJlcikgbHVtaW5vc2l0eVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5yZ2IyaHNsID0gZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgYiA9IHByZXBhcmVSR0IociwgZywgYik7XG4gICAgICAgIHIgPSBiWzBdO1xuICAgICAgICBnID0gYlsxXTtcbiAgICAgICAgYiA9IGJbMl07XG5cbiAgICAgICAgdmFyIEgsIFMsIEwsIE0sIG0sIEM7XG4gICAgICAgIE0gPSBtbWF4KHIsIGcsIGIpO1xuICAgICAgICBtID0gbW1pbihyLCBnLCBiKTtcbiAgICAgICAgQyA9IE0gLSBtO1xuICAgICAgICBIID0gKEMgPT0gMCA/IG51bGwgOlxuICAgICAgICAgICAgIE0gPT0gciA/IChnIC0gYikgLyBDIDpcbiAgICAgICAgICAgICBNID09IGcgPyAoYiAtIHIpIC8gQyArIDIgOlxuICAgICAgICAgICAgICAgICAgICAgIChyIC0gZykgLyBDICsgNCk7XG4gICAgICAgIEggPSAoKEggKyAzNjApICUgNikgKiA2MCAvIDM2MDtcbiAgICAgICAgTCA9IChNICsgbSkgLyAyO1xuICAgICAgICBTID0gKEMgPT0gMCA/IDAgOlxuICAgICAgICAgICAgIEwgPCAuNSA/IEMgLyAoMiAqIEwpIDpcbiAgICAgICAgICAgICAgICAgICAgICBDIC8gKDIgLSAyICogTCkpO1xuICAgICAgICByZXR1cm4ge2g6IEgsIHM6IFMsIGw6IEwsIHRvU3RyaW5nOiBoc2x0b1N0cmluZ307XG4gICAgfTtcbiAgICBSLl9wYXRoMnN0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuam9pbihcIixcIikucmVwbGFjZShwMnMsIFwiJDFcIik7XG4gICAgfTtcbiAgICBmdW5jdGlvbiByZXB1c2goYXJyYXksIGl0ZW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gYXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkrKykgaWYgKGFycmF5W2ldID09PSBpdGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJyYXkucHVzaChhcnJheS5zcGxpY2UoaSwgMSlbMF0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNhY2hlcihmLCBzY29wZSwgcG9zdHByb2Nlc3Nvcikge1xuICAgICAgICBmdW5jdGlvbiBuZXdmKCkge1xuICAgICAgICAgICAgdmFyIGFyZyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCksXG4gICAgICAgICAgICAgICAgYXJncyA9IGFyZy5qb2luKFwiXFx1MjQwMFwiKSxcbiAgICAgICAgICAgICAgICBjYWNoZSA9IG5ld2YuY2FjaGUgPSBuZXdmLmNhY2hlIHx8IHt9LFxuICAgICAgICAgICAgICAgIGNvdW50ID0gbmV3Zi5jb3VudCA9IG5ld2YuY291bnQgfHwgW107XG4gICAgICAgICAgICBpZiAoY2FjaGVbaGFzXShhcmdzKSkge1xuICAgICAgICAgICAgICAgIHJlcHVzaChjb3VudCwgYXJncyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc3Rwcm9jZXNzb3IgPyBwb3N0cHJvY2Vzc29yKGNhY2hlW2FyZ3NdKSA6IGNhY2hlW2FyZ3NdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY291bnQubGVuZ3RoID49IDFlMyAmJiBkZWxldGUgY2FjaGVbY291bnQuc2hpZnQoKV07XG4gICAgICAgICAgICBjb3VudC5wdXNoKGFyZ3MpO1xuICAgICAgICAgICAgY2FjaGVbYXJnc10gPSBmW2FwcGx5XShzY29wZSwgYXJnKTtcbiAgICAgICAgICAgI
57590HJldHVybiBwb3N0cHJvY2Vzc29yID8gcG9zdHByb2Nlc3NvcihjYWNoZVthcmdzXSkgOiBjYWNoZVthcmdzXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3ZjtcbiAgICB9XG5cbiAgICB2YXIgcHJlbG9hZCA9IFIuX3ByZWxvYWQgPSBmdW5jdGlvbiAoc3JjLCBmKSB7XG4gICAgICAgIHZhciBpbWcgPSBnLmRvYy5jcmVhdGVFbGVtZW50KFwiaW1nXCIpO1xuICAgICAgICBpbWcuc3R5bGUuY3NzVGV4dCA9IFwicG9zaXRpb246YWJzb2x1dGU7bGVmdDotOTk5OWVtO3RvcDotOTk5OWVtXCI7XG4gICAgICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBmLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLm9ubG9hZCA9IG51bGw7XG4gICAgICAgICAgICBnLmRvYy5ib2R5LnJlbW92ZUNoaWxkKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgICBpbWcub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGcuZG9jLmJvZHkucmVtb3ZlQ2hpbGQodGhpcyk7XG4gICAgICAgIH07XG4gICAgICAgIGcuZG9jLmJvZHkuYXBwZW5kQ2hpbGQoaW1nKTtcbiAgICAgICAgaW1nLnNyYyA9IHNyYztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2xyVG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhleDtcbiAgICB9XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRSR0JcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFBhcnNlcyBjb2xvdXIgc3RyaW5nIGFzIFJHQiBvYmplY3RcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gY29sb3VyIChzdHJpbmcpIGNvbG91ciBzdHJpbmcgaW4gb25lIG9mIGZvcm1hdHM6XG4gICAgICMgPHVsPlxuICAgICAjICAgICA8bGk+Q29sb3VyIG5hbWUgKOKAnDxjb2RlPnJlZDwvY29kZT7igJ0sIOKAnDxjb2RlPmdyZWVuPC9jb2RlPuKAnSwg4oCcPGNvZGU+Y29ybmZsb3dlcmJsdWU8L2NvZGU+4oCdLCBldGMpPC9saT5cbiAgICAgIyAgICAgPGxpPiPigKLigKLigKIg4oCUIHNob3J0ZW5lZCBIVE1MIGNvbG91cjogKOKAnDxjb2RlPiMwMDA8L2NvZGU+4oCdLCDigJw8Y29kZT4jZmMwPC9jb2RlPuKAnSwgZXRjKTwvbGk+XG4gICAgICMgICAgIDxsaT4j4oCi4oCi4oCi4oCi4oCi4oCiIOKAlCBmdWxsIGxlbmd0aCBIVE1MIGNvbG91cjogKOKAnDxjb2RlPiMwMDAwMDA8L2NvZGU+4oCdLCDigJw8Y29kZT4jYmQyMzAwPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiKOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCByZWQsIGdyZWVuIGFuZCBibHVlIGNoYW5uZWxz4oCZIHZhbHVlczogKOKAnDxjb2RlPnJnYigyMDAsJm5ic3A7MTAwLCZuYnNwOzApPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiKOKAouKAouKAoiUsIOKAouKAouKAoiUsIOKAouKAouKAoiUpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgaW4gJTogKOKAnDxjb2RlPnJnYigxMDAlLCZuYnNwOzE3NSUsJm5ic3A7MCUpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+aHNiKOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBodWUsIHNhdHVyYXRpb24gYW5kIGJyaWdodG5lc3MgdmFsdWVzOiAo4oCcPGNvZGU+aHNiKDAuNSwmbmJzcDswLjI1LCZuYnNwOzEpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+aHNiKOKAouKAouKAoiUsIOKAouKAouKAoiUsIOKAouKAouKAoiUpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgaW4gJTwvbGk+XG4gICAgICMgICAgIDxsaT5oc2wo4oCi4oCi4oCiLCDigKLigKLigKIsIOKAouKAouKAoikg4oCUIHNhbWUgYXMgaHNiPC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBoc2I8L2xpPlxuICAgICAjIDwvdWw+XG4gICAgID0gKG9iamVjdCkgUkdCIG9iamVjdCBpbiBmb3JtYXQ6XG4gICAgIG8ge1xuICAgICBvICAgICByIChudW1iZXIpIHJlZCxcbiAgICAgbyAgICAgZyAobnVtYmVyKSBncmVlbixcbiAgICAgbyAgICAgYiAobnVtYmVyKSBibHVlXG4gICAgIG8gICAgIGhleCAoc3RyaW5nKSBjb2xvciBpbiBIVE1ML0NTUyBmb3JtYXQ6ICPigKLigKLigKLigKLigKLigKIsXG4gICAgIG8gICAgIGVycm9yIChib29sZWFuKSB0cnVlIGlmIHN0cmluZyBjYW7igJl0IGJlIHBhcnNlZFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5nZXRSR0IgPSBjYWNoZXIoZnVuY3Rpb24gKGNvbG91cikge1xuICAgICAgICBpZiAoIWNvbG91ciB8fCAhISgoY29sb3VyID0gU3RyKGNvbG91cikpLmluZGV4T2YoXCItXCIpICsgMSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7cjogLTEsIGc6IC0xLCBiOiAtMSwgaGV4OiBcIm5vbmVcIiwgZXJyb3I6IDEsIHRvU3RyaW5nOiBjbHJUb1N0cmluZ307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbG91ciA9PSBcIm5vbmVcIikge1xuICAgICAgICAgICAgcmV0dXJuIHtyOiAtMSwgZzogLTEsIGI6IC0xLCBoZXg6IFwibm9uZVwiLCB0b1N0cmluZzogY2xyVG9TdHJpbmd9O1xuICAgICAgICB9XG4gICAgICAgICEoaHNyZ1toYXNdKGNvbG91ci50b0xvd2VyQ2FzZSgpLnN1YnN0cmluZygwLCAyKSkgfHwgY29sb3VyLmNoYXJBdCgpID09IFwiI1wiKSAmJiAoY29sb3VyID0gdG9IZXgoY29sb3VyKSk7XG4gICAgICAgIHZhciByZXMsXG4gICAgICAgICAgICByZWQsXG4gICAgICAgICAgICBncmVlbixcbiAgICAgICAgICAgIGJsdWUsXG4gICAgICAgICAgICBvcGFjaXR5LFxuICAgICAgICAgICAgdCxcbiAgICAgICAgICAgIHZhbHVlcyxcbiAgICAgICAgICAgIHJnYiA9IGNvbG91ci5tYXRjaChjb2xvdXJSZWdFeHApO1xuICAgICAgICBpZiAocmdiKSB7XG4gICAgICAgICAgICBpZiAocmdiWzJdKSB7XG4gICAgICAgICAgICAgICAgYmx1ZSA9IHRvSW50KHJnYlsyXS5zdWJzdHJpbmcoNSksIDE2KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvSW50KHJnYlsyXS5zdWJzdHJpbmcoMywgNSksIDE2KTtcbiAgICAgICAgICAgICAgICByZWQgPSB0b0ludChyZ2JbMl0uc3Vic3RyaW5nKDEsIDMpLCAxNik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzNdKSB7XG4gICAgICAgICAgICAgICAgYmx1ZSA9IHRvSW50KCh0ID0gcmdiWzNdLmNoYXJBdCgzKSkgKyB0LCAxNik7XG4gICAgICAgICAgICAgICAgZ3JlZW4gPSB0b0ludCgodCA9IHJnYlszXS5jaGFyQXQoMikpICsgdCwgMTYpO1xuICAgICAgICAgICAgICAgI
57590HJlZCA9IHRvSW50KCh0ID0gcmdiWzNdLmNoYXJBdCgxKSkgKyB0LCAxNik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzRdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzRdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgcmdiWzFdLnRvTG93ZXJDYXNlKCkuc2xpY2UoMCwgNCkgPT0gXCJyZ2JhXCIgJiYgKG9wYWNpdHkgPSB0b0Zsb2F0KHZhbHVlc1szXSkpO1xuICAgICAgICAgICAgICAgIHZhbHVlc1szXSAmJiB2YWx1ZXNbM10uc2xpY2UoLTEpID09IFwiJVwiICYmIChvcGFjaXR5IC89IDEwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzVdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzVdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgKHZhbHVlc1swXS5zbGljZSgtMykgPT0gXCJkZWdcIiB8fCB2YWx1ZXNbMF0uc2xpY2UoLTEpID09IFwiXFx4YjBcIikgJiYgKHJlZCAvPSAzNjApO1xuICAgICAgICAgICAgICAgIHJnYlsxXS50b0xvd2VyQ2FzZSgpLnNsaWNlKDAsIDQpID09IFwiaHNiYVwiICYmIChvcGFjaXR5ID0gdG9GbG9hdCh2YWx1ZXNbM10pKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbM10gJiYgdmFsdWVzWzNdLnNsaWNlKC0xKSA9PSBcIiVcIiAmJiAob3BhY2l0eSAvPSAxMDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBSLmhzYjJyZ2IocmVkLCBncmVlbiwgYmx1ZSwgb3BhY2l0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiWzZdKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzID0gcmdiWzZdW3NwbGl0XShjb21tYVNwYWNlcyk7XG4gICAgICAgICAgICAgICAgcmVkID0gdG9GbG9hdCh2YWx1ZXNbMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKHJlZCAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBncmVlbiA9IHRvRmxvYXQodmFsdWVzWzFdKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbMV0uc2xpY2UoLTEpID09IFwiJVwiICYmIChncmVlbiAqPSAyLjU1KTtcbiAgICAgICAgICAgICAgICBibHVlID0gdG9GbG9hdCh2YWx1ZXNbMl0pO1xuICAgICAgICAgICAgICAgIHZhbHVlc1syXS5zbGljZSgtMSkgPT0gXCIlXCIgJiYgKGJsdWUgKj0gMi41NSk7XG4gICAgICAgICAgICAgICAgKHZhbHVlc1swXS5zbGljZSgtMykgPT0gXCJkZWdcIiB8fCB2YWx1ZXNbMF0uc2xpY2UoLTEpID09IFwiXFx4YjBcIikgJiYgKHJlZCAvPSAzNjApO1xuICAgICAgICAgICAgICAgIHJnYlsxXS50b0xvd2VyQ2FzZSgpLnNsaWNlKDAsIDQpID09IFwiaHNsYVwiICYmIChvcGFjaXR5ID0gdG9GbG9hdCh2YWx1ZXNbM10pKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXNbM10gJiYgdmFsdWVzWzNdLnNsaWNlKC0xKSA9PSBcIiVcIiAmJiAob3BhY2l0eSAvPSAxMDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBSLmhzbDJyZ2IocmVkLCBncmVlbiwgYmx1ZSwgb3BhY2l0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZ2IgPSB7cjogcmVkLCBnOiBncmVlbiwgYjogYmx1ZSwgdG9TdHJpbmc6IGNsclRvU3RyaW5nfTtcbiAgICAgICAgICAgIHJnYi5oZXggPSBcIiNcIiArICgxNjc3NzIxNiB8IGJsdWUgfCAoZ3JlZW4gPDwgOCkgfCAocmVkIDw8IDE2KSkudG9TdHJpbmcoMTYpLnNsaWNlKDEpO1xuICAgICAgICAgICAgUi5pcyhvcGFjaXR5LCBcImZpbml0ZVwiKSAmJiAocmdiLm9wYWNpdHkgPSBvcGFjaXR5KTtcbiAgICAgICAgICAgIHJldHVybiByZ2I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtyOiAtMSwgZzogLTEsIGI6IC0xLCBoZXg6IFwibm9uZVwiLCBlcnJvcjogMSwgdG9TdHJpbmc6IGNsclRvU3RyaW5nfTtcbiAgICB9LCBSKTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5oc2JcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENvbnZlcnRzIEhTQiB2YWx1ZXMgdG8gaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjb2xvdXIuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGggKG51bWJlcikgaHVlXG4gICAgIC0gcyAobnVtYmVyKSBzYXR1cmF0aW9uXG4gICAgIC0gYiAobnVtYmVyKSB2YWx1ZSBvciBicmlnaHRuZXNzXG4gICAgID0gKHN0cmluZykgaGV4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjb2xvdXIuXG4gICAgXFwqL1xuICAgIFIuaHNiID0gY2FjaGVyKGZ1bmN0aW9uIChoLCBzLCBiKSB7XG4gICAgICAgIHJldHVybiBSLmhzYjJyZ2IoaCwgcywgYikuaGV4O1xuICAgIH0pO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmhzbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ29udmVydHMgSFNMIHZhbHVlcyB0byBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaCAobnVtYmVyKSBodWVcbiAgICAgLSBzIChudW1iZXIpIHNhdHVyYXRpb25cbiAgICAgLSBsIChudW1iZXIpIGx1bWlub3NpdHlcbiAgICAgPSAoc3RyaW5nKSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICBcXCovXG4gICAgUi5oc2wgPSBjYWNoZXIoZnVuY3Rpb24gKGgsIHMsIGwpIHtcbiAgICAgICAgcmV0dXJuIFIuaHNsMnJnYihoLCBzLCBsKS5oZXg7XG4gICAgfSk7XG4gICAgLypcXFxuICAgICAqIFJhcGh
57590hZWwucmdiXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBSR0IgdmFsdWVzIHRvIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgY29sb3VyLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSByIChudW1iZXIpIHJlZFxuICAgICAtIGcgKG51bWJlcikgZ3JlZW5cbiAgICAgLSBiIChudW1iZXIpIGJsdWVcbiAgICAgPSAoc3RyaW5nKSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGNvbG91ci5cbiAgICBcXCovXG4gICAgUi5yZ2IgPSBjYWNoZXIoZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgZnVuY3Rpb24gcm91bmQoeCkgeyByZXR1cm4gKHggKyAwLjUpIHwgMDsgfVxuICAgICAgICByZXR1cm4gXCIjXCIgKyAoMTY3NzcyMTYgfCByb3VuZChiKSB8IChyb3VuZChnKSA8PCA4KSB8IChyb3VuZChyKSA8PCAxNikpLnRvU3RyaW5nKDE2KS5zbGljZSgxKTtcbiAgICB9KTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRDb2xvclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogT24gZWFjaCBjYWxsIHJldHVybnMgbmV4dCBjb2xvdXIgaW4gdGhlIHNwZWN0cnVtLiBUbyByZXNldCBpdCBiYWNrIHRvIHJlZCBjYWxsIEBSYXBoYWVsLmdldENvbG9yLnJlc2V0XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHZhbHVlIChudW1iZXIpICNvcHRpb25hbCBicmlnaHRuZXNzLCBkZWZhdWx0IGlzIGAwLjc1YFxuICAgICA9IChzdHJpbmcpIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgY29sb3VyLlxuICAgIFxcKi9cbiAgICBSLmdldENvbG9yID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBzdGFydCA9IHRoaXMuZ2V0Q29sb3Iuc3RhcnQgPSB0aGlzLmdldENvbG9yLnN0YXJ0IHx8IHtoOiAwLCBzOiAxLCBiOiB2YWx1ZSB8fCAuNzV9LFxuICAgICAgICAgICAgcmdiID0gdGhpcy5oc2IycmdiKHN0YXJ0LmgsIHN0YXJ0LnMsIHN0YXJ0LmIpO1xuICAgICAgICBzdGFydC5oICs9IC4wNzU7XG4gICAgICAgIGlmIChzdGFydC5oID4gMSkge1xuICAgICAgICAgICAgc3RhcnQuaCA9IDA7XG4gICAgICAgICAgICBzdGFydC5zIC09IC4yO1xuICAgICAgICAgICAgc3RhcnQucyA8PSAwICYmICh0aGlzLmdldENvbG9yLnN0YXJ0ID0ge2g6IDAsIHM6IDEsIGI6IHN0YXJ0LmJ9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmdiLmhleDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmdldENvbG9yLnJlc2V0XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXNldHMgc3BlY3RydW0gcG9zaXRpb24gZm9yIEBSYXBoYWVsLmdldENvbG9yIGJhY2sgdG8gcmVkLlxuICAgIFxcKi9cbiAgICBSLmdldENvbG9yLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBkZWxldGUgdGhpcy5zdGFydDtcbiAgICB9O1xuXG4gICAgLy8gaHR0cDovL3NjaGVwZXJzLmNjL2dldHRpbmctdG8tdGhlLXBvaW50XG4gICAgZnVuY3Rpb24gY2F0bXVsbFJvbTJiZXppZXIoY3JwLCB6KSB7XG4gICAgICAgIHZhciBkID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpTGVuID0gY3JwLmxlbmd0aDsgaUxlbiAtIDIgKiAheiA+IGk7IGkgKz0gMikge1xuICAgICAgICAgICAgdmFyIHAgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7eDogK2NycFtpIC0gMl0sIHk6ICtjcnBbaSAtIDFdfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHt4OiArY3JwW2ldLCAgICAgeTogK2NycFtpICsgMV19LFxuICAgICAgICAgICAgICAgICAgICAgICAge3g6ICtjcnBbaSArIDJdLCB5OiArY3JwW2kgKyAzXX0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7eDogK2NycFtpICsgNF0sIHk6ICtjcnBbaSArIDVdfVxuICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYgKHopIHtcbiAgICAgICAgICAgICAgICBpZiAoIWkpIHtcbiAgICAgICAgICAgICAgICAgICAgcFswXSA9IHt4OiArY3JwW2lMZW4gLSAyXSwgeTogK2NycFtpTGVuIC0gMV19O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaUxlbiAtIDQgPT0gaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzNdID0ge3g6ICtjcnBbMF0sIHk6ICtjcnBbMV19O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaUxlbiAtIDIgPT0gaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzJdID0ge3g6ICtjcnBbMF0sIHk6ICtjcnBbMV19O1xuICAgICAgICAgICAgICAgICAgICBwWzNdID0ge3g6ICtjcnBbMl0sIHk6ICtjcnBbM119O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlMZW4gLSA0ID09IGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcFszXSA9IHBbMl07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaSkge1xuICAgICAgICAgICAgICAgICAgICBwWzBdID0ge3g6ICtjcnBbaV0sIHk6ICtjcnBbaSArIDFdfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkLnB1c2goW1wiQ1wiLFxuICAgICAgICAgICAgICAgICAgKC1wWzBdLnggKyA2ICogcFsxXS54ICsgcFsyXS54KSAvIDYsXG4gICAgICAgICAgICAgICAgICAoLXBbMF0ueSArIDYgKiBwWzFdLnkgKyBwWzJdLnkpIC8gNixcbiAgICAgICAgICAgICAgICAgIChwWzFdLnggKyA2ICogcFsyXS54IC0gcFszXS54KSAvIDYsXG4gICAgICAgICAgICAgICAgICAocFsxXS55ICsgNipwWzJdLnkgLSBwWzNdLnkpIC8gNixcbiAgICAgICAgICAgICAgICAgIHBbMl0ueCxcbiAgICAgICAgICAgICAgICAgIHBbMl0ueVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZDtcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGFyc2VQYXRoU3RyaW5nXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIFBhcnNlcyBnaXZlbiBwYXRoIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIGFycmF5cyBvZiBwYXRoIHNlZ21lbnRzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBwYXRoU3RyaW5nIChzdHJpbmd8YXJyYXkpIHBhdGggc3RyaW5nIG9yIGFycmF5IG9mIHNlZ21lbnRzIChpbiB0aGUgbGFzdCBjYXNlIGl0IHdpbGwgYmUgcmV0dXJuZWQgc3RyYWlnaHQgYXdheSlcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHNlZ21lbnRzLlxuICAgIFxcKi9cbiAgICBSLnBhcnNlUGF0aFN0cmluZyA9IGZ1bmN0aW9uIChwYXRoU3RyaW5nKSB7XG4gICAgICAgIGlmICghcGF0aFN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgI
57590H1cbiAgICAgICAgdmFyIHB0aCA9IHBhdGhzKHBhdGhTdHJpbmcpO1xuICAgICAgICBpZiAocHRoLmFycikge1xuICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguYXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwYXJhbUNvdW50cyA9IHthOiA3LCBjOiA2LCBoOiAxLCBsOiAyLCBtOiAyLCByOiA0LCBxOiA0LCBzOiA0LCB0OiAyLCB2OiAxLCB6OiAwfSxcbiAgICAgICAgICAgIGRhdGEgPSBbXTtcbiAgICAgICAgaWYgKFIuaXMocGF0aFN0cmluZywgYXJyYXkpICYmIFIuaXMocGF0aFN0cmluZ1swXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgIGRhdGEgPSBwYXRoQ2xvbmUocGF0aFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgU3RyKHBhdGhTdHJpbmcpLnJlcGxhY2UocGF0aENvbW1hbmQsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gYi50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGMucmVwbGFjZShwYXRoVmFsdWVzLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgICAgICBiICYmIHBhcmFtcy5wdXNoKCtiKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSA9PSBcIm1cIiAmJiBwYXJhbXMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgICAgICBkYXRhLnB1c2goW2JdW2NvbmNhdF0ocGFyYW1zLnNwbGljZSgwLCAyKSkpO1xuICAgICAgICAgICAgICAgICAgICBuYW1lID0gXCJsXCI7XG4gICAgICAgICAgICAgICAgICAgIGIgPSBiID09IFwibVwiID8gXCJsXCIgOiBcIkxcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5hbWUgPT0gXCJyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5wdXNoKFtiXVtjb25jYXRdKHBhcmFtcykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB3aGlsZSAocGFyYW1zLmxlbmd0aCA+PSBwYXJhbUNvdW50c1tuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhLnB1c2goW2JdW2NvbmNhdF0ocGFyYW1zLnNwbGljZSgwLCBwYXJhbUNvdW50c1tuYW1lXSkpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJhbUNvdW50c1tuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhLnRvU3RyaW5nID0gUi5fcGF0aDJzdHJpbmc7XG4gICAgICAgIHB0aC5hcnIgPSBwYXRoQ2xvbmUoZGF0YSk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGFyc2VUcmFuc2Zvcm1TdHJpbmdcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogUGFyc2VzIGdpdmVuIHBhdGggc3RyaW5nIGludG8gYW4gYXJyYXkgb2YgdHJhbnNmb3JtYXRpb25zLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBUU3RyaW5nIChzdHJpbmd8YXJyYXkpIHRyYW5zZm9ybSBzdHJpbmcgb3IgYXJyYXkgb2YgdHJhbnNmb3JtYXRpb25zIChpbiB0aGUgbGFzdCBjYXNlIGl0IHdpbGwgYmUgcmV0dXJuZWQgc3RyYWlnaHQgYXdheSlcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHRyYW5zZm9ybWF0aW9ucy5cbiAgICBcXCovXG4gICAgUi5wYXJzZVRyYW5zZm9ybVN0cmluZyA9IGNhY2hlcihmdW5jdGlvbiAoVFN0cmluZykge1xuICAgICAgICBpZiAoIVRTdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbUNvdW50cyA9IHtyOiAzLCBzOiA0LCB0OiAyLCBtOiA2fSxcbiAgICAgICAgICAgIGRhdGEgPSBbXTtcbiAgICAgICAgaWYgKFIuaXMoVFN0cmluZywgYXJyYXkpICYmIFIuaXMoVFN0cmluZ1swXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgIGRhdGEgPSBwYXRoQ2xvbmUoVFN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgU3RyKFRTdHJpbmcpLnJlcGxhY2UodENvbW1hbmQsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gbG93ZXJDYXNlLmNhbGwoYik7XG4gICAgICAgICAgICAgICAgYy5yZXBsYWNlKHBhdGhWYWx1ZXMsIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGIgJiYgcGFyYW1zLnB1c2goK2IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRhdGEucHVzaChbYl1bY29uY2F0XShwYXJhbXMpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGRhdGEudG9TdHJpbmcgPSBSLl9wYXR
57590oMnN0cmluZztcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSwgdGhpcywgZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICBpZiAoIWVsZW0pIHJldHVybiBlbGVtO1xuICAgICAgICB2YXIgbmV3RGF0YSA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW0ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBuZXdMZXZlbCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBlbGVtW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbmV3TGV2ZWwucHVzaChlbGVtW2ldW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld0RhdGEucHVzaChuZXdMZXZlbCk7XG4gICAgICAgIH1cbiAgICAgIHJldHVybiBuZXdEYXRhOyB9ICk7XG4gICAgLy8gUEFUSFNcbiAgICB2YXIgcGF0aHMgPSBmdW5jdGlvbiAocHMpIHtcbiAgICAgICAgdmFyIHAgPSBwYXRocy5wcyA9IHBhdGhzLnBzIHx8IHt9O1xuICAgICAgICBpZiAocFtwc10pIHtcbiAgICAgICAgICAgIHBbcHNdLnNsZWVwID0gMTAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcFtwc10gPSB7XG4gICAgICAgICAgICAgICAgc2xlZXA6IDEwMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwKSBpZiAocFtoYXNdKGtleSkgJiYga2V5ICE9IHBzKSB7XG4gICAgICAgICAgICAgICAgcFtrZXldLnNsZWVwLS07XG4gICAgICAgICAgICAgICAgIXBba2V5XS5zbGVlcCAmJiBkZWxldGUgcFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHBbcHNdO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuZmluZERvdHNBdFNlZ21lbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogRmluZCBkb3QgY29vcmRpbmF0ZXMgb24gdGhlIGdpdmVuIGN1YmljIGJlemllciBjdXJ2ZSBhdCB0aGUgZ2l2ZW4gdC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcDF4IChudW1iZXIpIHggb2YgdGhlIGZpcnN0IHBvaW50IG9mIHRoZSBjdXJ2ZVxuICAgICAtIHAxeSAobnVtYmVyKSB5IG9mIHRoZSBmaXJzdCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBjMXggKG51bWJlcikgeCBvZiB0aGUgZmlyc3QgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMxeSAobnVtYmVyKSB5IG9mIHRoZSBmaXJzdCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gYzJ4IChudW1iZXIpIHggb2YgdGhlIHNlY29uZCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gYzJ5IChudW1iZXIpIHkgb2YgdGhlIHNlY29uZCBhbmNob3Igb2YgdGhlIGN1cnZlXG4gICAgIC0gcDJ4IChudW1iZXIpIHggb2YgdGhlIHNlY29uZCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBwMnkgKG51bWJlcikgeSBvZiB0aGUgc2Vjb25kIHBvaW50IG9mIHRoZSBjdXJ2ZVxuICAgICAtIHQgKG51bWJlcikgcG9zaXRpb24gb24gdGhlIGN1cnZlICgwLi4xKVxuICAgICA9IChvYmplY3QpIHBvaW50IGluZm9ybWF0aW9uIGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgbyAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICBtOiB7XG4gICAgIG8gICAgICAgICB4OiAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgYW5jaG9yXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgYW5jaG9yXG4gICAgIG8gICAgIH1cbiAgICAgbyAgICAgbjoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSByaWdodCBhbmNob3JcbiAgICAgbyAgICAgICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYW5jaG9yXG4gICAgIG8gICAgIH1cbiAgICAgbyAgICAgc3RhcnQ6IHtcbiAgICAgbyAgICAgICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgc3RhcnQgb2YgdGhlIGN1cnZlXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHN0YXJ0IG9mIHRoZSBjdXJ2ZVxuICAgICBvICAgICB9XG4gICAgIG8gICAgIGVuZDoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBlbmQgb2YgdGhlIGN1cnZlXG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGVuZCBvZiB0aGUgY3VydmVcbiAgICAgbyAgICAgfVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgdGhlIGN1cnZlIGRlcml2YXRpdmUgYXQgdGhlIHBvaW50XG4gICAgIG8gfVxuICAgIFxcKi9cbiAgICBSLmZpbmREb3RzQXRTZWdtZW50ID0gZnVuY3Rpb24gKHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0KSB7XG4gICAgICAgIHZhciB0MSA9IDEgLSB0LFxuICAgICAgICAgICAgdDEzID0gcG93KHQxLCAzKSxcbiAgICAgICAgICAgIHQxMiA9IHBvdyh0MSwgMiksXG4gICAgICAgICAgICB0MiA9IHQgKiB0LFxuICAgICAgICAgICAgdDMgPSB0MiAqIHQsXG4gICAgICAgICAgICB4ID0gdDEzICogcDF4ICsgdDEyICogMyAqIHQgKiBjMXggKyB0MSAqIDMgKiB0ICogdCAqIGMyeCArIHQzICogcDJ4LFxuICAgICAgICAgICAgeSA9IHQxMyAqIHAxeSArIHQxMiAqIDMgKiB0ICogYzF5ICsgdDEgKiAzICogdCAqIHQgKiBjMnkgKyB0MyAqIHAyeSxcbiAgICAgICAgICAgIG14ID0gcDF4ICsgMiAqIHQgKiAoYzF4IC0gcDF4KSArIHQyICogKGMyeCAtIDIgKiBjMXggKyBwMXgpLFxuICAgICAgICAgICAgbXkgPSBwMXkgKyAyICogdCAqIChjMXkgLSBwMXkpICsgdDIgKiAoYzJ5IC0gMiAqIGMxeSArIHAxeSksXG4gICAgICAgICAgICBueCA9IGMxeCArIDIgKiB0ICogKGMyeCAtIGMxeCkgKyB0MiAqIChwMnggLSAyICogYzJ4ICsgYzF4KSxcbiAgICAgICAgICAgIG55ID0gYzF5ICsgMiAqIHQgKiAoYzJ5IC0gYzF5KSArIHQyICogKHAyeSAtIDIgKiBjMnkgKyBjMXkpLFxuICAgICAgICAgICAgYXggPSB0MSAqIHAxeCArIHQgKiBjMXgsXG4gICAgICAgICAgICBheSA9IHQxICogcDF5ICsgdCAqIGMxeSxcbiAgICAgICAgICAgIGN4ID0gdDEgKiBjMnggKyB0ICogcDJ4LFxuICAgICAgICAgICAgY3kgPSB0MSAqIGMyeSArIHQgKiBwMnksXG4gICAgICAgICAgICBhbHBoYSA9ICg5MCAtIG1hdGguYXRhbjIobXggLSBueCwgbXkgLSBueSkgKiAxODAgLyBQSSk7XG4gICAgICAgIChteCA+IG54IHx8IG15IDwgbnkpICYmIChhbHBoYSArPSAxODApO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgI
57590Hk6IHksXG4gICAgICAgICAgICBtOiB7eDogbXgsIHk6IG15fSxcbiAgICAgICAgICAgIG46IHt4OiBueCwgeTogbnl9LFxuICAgICAgICAgICAgc3RhcnQ6IHt4OiBheCwgeTogYXl9LFxuICAgICAgICAgICAgZW5kOiB7eDogY3gsIHk6IGN5fSxcbiAgICAgICAgICAgIGFscGhhOiBhbHBoYVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuYmV6aWVyQkJveFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm4gYm91bmRpbmcgYm94IG9mIGEgZ2l2ZW4gY3ViaWMgYmV6aWVyIGN1cnZlXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHAxeCAobnVtYmVyKSB4IG9mIHRoZSBmaXJzdCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgLSBwMXkgKG51bWJlcikgeSBvZiB0aGUgZmlyc3QgcG9pbnQgb2YgdGhlIGN1cnZlXG4gICAgIC0gYzF4IChudW1iZXIpIHggb2YgdGhlIGZpcnN0IGFuY2hvciBvZiB0aGUgY3VydmVcbiAgICAgLSBjMXkgKG51bWJlcikgeSBvZiB0aGUgZmlyc3QgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMyeCAobnVtYmVyKSB4IG9mIHRoZSBzZWNvbmQgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIGMyeSAobnVtYmVyKSB5IG9mIHRoZSBzZWNvbmQgYW5jaG9yIG9mIHRoZSBjdXJ2ZVxuICAgICAtIHAyeCAobnVtYmVyKSB4IG9mIHRoZSBzZWNvbmQgcG9pbnQgb2YgdGhlIGN1cnZlXG4gICAgIC0gcDJ5IChudW1iZXIpIHkgb2YgdGhlIHNlY29uZCBwb2ludCBvZiB0aGUgY3VydmVcbiAgICAgKiBvclxuICAgICAtIGJleiAoYXJyYXkpIGFycmF5IG9mIHNpeCBwb2ludHMgZm9yIGJlemllciBjdXJ2ZVxuICAgICA9IChvYmplY3QpIHBvaW50IGluZm9ybWF0aW9uIGluIGZvcm1hdDpcbiAgICAgbyB7XG4gICAgIG8gICAgIG1pbjoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBsZWZ0IHBvaW50XG4gICAgIG8gICAgICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHRvcCBwb2ludFxuICAgICBvICAgICB9XG4gICAgIG8gICAgIG1heDoge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSByaWdodCBwb2ludFxuICAgICBvICAgICAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBib3R0b20gcG9pbnRcbiAgICAgbyAgICAgfVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5iZXppZXJCQm94ID0gZnVuY3Rpb24gKHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5KSB7XG4gICAgICAgIGlmICghUi5pcyhwMXgsIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIHAxeCA9IFtwMXgsIHAxeSwgYzF4LCBjMXksIGMyeCwgYzJ5LCBwMngsIHAyeV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJib3ggPSBjdXJ2ZURpbS5hcHBseShudWxsLCBwMXgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogYmJveC5taW4ueCxcbiAgICAgICAgICAgIHk6IGJib3gubWluLnksXG4gICAgICAgICAgICB4MjogYmJveC5tYXgueCxcbiAgICAgICAgICAgIHkyOiBiYm94Lm1heC55LFxuICAgICAgICAgICAgd2lkdGg6IGJib3gubWF4LnggLSBiYm94Lm1pbi54LFxuICAgICAgICAgICAgaGVpZ2h0OiBiYm94Lm1heC55IC0gYmJveC5taW4ueVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuaXNQb2ludEluc2lkZUJCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICoqXG4gICAgICogUmV0dXJucyBgdHJ1ZWAgaWYgZ2l2ZW4gcG9pbnQgaXMgaW5zaWRlIGJvdW5kaW5nIGJveGVzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBiYm94IChzdHJpbmcpIGJvdW5kaW5nIGJveFxuICAgICAtIHggKHN0cmluZykgeCBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICAtIHkgKHN0cmluZykgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICA9IChib29sZWFuKSBgdHJ1ZWAgaWYgcG9pbnQgaW5zaWRlXG4gICAgXFwqL1xuICAgIFIuaXNQb2ludEluc2lkZUJCb3ggPSBmdW5jdGlvbiAoYmJveCwgeCwgeSkge1xuICAgICAgICByZXR1cm4geCA+PSBiYm94LnggJiYgeCA8PSBiYm94LngyICYmIHkgPj0gYmJveC55ICYmIHkgPD0gYmJveC55MjtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLmlzQkJveEludGVyc2VjdFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiB0d28gYm91bmRpbmcgYm94ZXMgaW50ZXJzZWN0XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGJib3gxIChzdHJpbmcpIGZpcnN0IGJvdW5kaW5nIGJveFxuICAgICAtIGJib3gyIChzdHJpbmcpIHNlY29uZCBib3VuZGluZyBib3hcbiAgICAgPSAoYm9vbGVhbikgYHRydWVgIGlmIHRoZXkgaW50ZXJzZWN0XG4gICAgXFwqL1xuICAgIFIuaXNCQm94SW50ZXJzZWN0ID0gZnVuY3Rpb24gKGJib3gxLCBiYm94Mikge1xuICAgICAgICB2Y
57590XIgaSA9IFIuaXNQb2ludEluc2lkZUJCb3g7XG4gICAgICAgIHJldHVybiBpKGJib3gyLCBiYm94MS54LCBiYm94MS55KVxuICAgICAgICAgICAgfHwgaShiYm94MiwgYmJveDEueDIsIGJib3gxLnkpXG4gICAgICAgICAgICB8fCBpKGJib3gyLCBiYm94MS54LCBiYm94MS55MilcbiAgICAgICAgICAgIHx8IGkoYmJveDIsIGJib3gxLngyLCBiYm94MS55MilcbiAgICAgICAgICAgIHx8IGkoYmJveDEsIGJib3gyLngsIGJib3gyLnkpXG4gICAgICAgICAgICB8fCBpKGJib3gxLCBiYm94Mi54MiwgYmJveDIueSlcbiAgICAgICAgICAgIHx8IGkoYmJveDEsIGJib3gyLngsIGJib3gyLnkyKVxuICAgICAgICAgICAgfHwgaShiYm94MSwgYmJveDIueDIsIGJib3gyLnkyKVxuICAgICAgICAgICAgfHwgKGJib3gxLnggPCBiYm94Mi54MiAmJiBiYm94MS54ID4gYmJveDIueCB8fCBiYm94Mi54IDwgYmJveDEueDIgJiYgYmJveDIueCA+IGJib3gxLngpXG4gICAgICAgICAgICAmJiAoYmJveDEueSA8IGJib3gyLnkyICYmIGJib3gxLnkgPiBiYm94Mi55IHx8IGJib3gyLnkgPCBiYm94MS55MiAmJiBiYm94Mi55ID4gYmJveDEueSk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBiYXNlMyh0LCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICB2YXIgdDEgPSAtMyAqIHAxICsgOSAqIHAyIC0gOSAqIHAzICsgMyAqIHA0LFxuICAgICAgICAgICAgdDIgPSB0ICogdDEgKyA2ICogcDEgLSAxMiAqIHAyICsgNiAqIHAzO1xuICAgICAgICByZXR1cm4gdCAqIHQyIC0gMyAqIHAxICsgMyAqIHAyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBiZXpsZW4oeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0LCB6KSB7XG4gICAgICAgIGlmICh6ID09IG51bGwpIHtcbiAgICAgICAgICAgIHogPSAxO1xuICAgICAgICB9XG4gICAgICAgIHogPSB6ID4gMSA/IDEgOiB6IDwgMCA/IDAgOiB6O1xuICAgICAgICB2Y
57590XIgejIgPSB6IC8gMixcbiAgICAgICAgICAgIG4gPSAxMixcbiAgICAgICAgICAgIFR2YWx1ZXMgPSBbLTAuMTI1MiwwLjEyNTIsLTAuMzY3OCwwLjM2NzgsLTAuNTg3MywwLjU4NzMsLTAuNzY5OSwwLjc2OTksLTAuOTA0MSwwLjkwNDEsLTAuOTgxNiwwLjk4MTZdLFxuICAgICAgICAgICAgQ3ZhbHVlcyA9IFswLjI0OTEsMC4yNDkxLDAuMjMzNSwwLjIzMzUsMC4yMDMyLDAuMjAzMiwwLjE2MDEsMC4xNjAxLDAuMTA2OSwwLjEwNjksMC4wNDcyLDAuMDQ3Ml0sXG4gICAgICAgICAgICBzdW0gPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgdmFyIGN0ID0gejIgKiBUdmFsdWVzW2ldICsgejIsXG4gICAgICAgICAgICAgICAgeGJhc2UgPSBiYXNlMyhjdCwgeDEsIHgyLCB4MywgeDQpLFxuICAgICAgICAgICAgICAgIHliYXNlID0gYmFzZTMoY3QsIHkxLCB5MiwgeTMsIHk0KSxcbiAgICAgICAgICAgICAgICBjb21iID0geGJhc2UgKiB4YmFzZSArIHliYXNlICogeWJhc2U7XG4gICAgICAgICAgICBzdW0gKz0gQ3ZhbHVlc1tpXSAqIG1hdGguc3FydChjb21iKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gejIgKiBzdW07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGdldFRhdExlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIGxsKSB7XG4gICAgICAgIGlmIChsbCA8IDAgfHwgYmV6bGVuKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIHg0LCB5NCkgPCBsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0ID0gMSxcbiAgICAgICAgICAgIHN0ZXAgPSB0IC8gMixcbiAgICAgICAgICAgIHQyID0gdCAtIHN0ZXAsXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgZSA9IC4wMTtcbiAgICAgICAgbCA9IGJlemxlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIHQyKTtcbiAgICAgICAgd2hpbGUgKGFicyhsIC0gbGwpID4gZSkge1xuICAgICAgICAgICAgc3RlcCAvPSAyO1xuICAgICAgICAgICAgdDIgKz0gKGwgPCBsbCA/IDEgOiAtMSkgKiBzdGVwO1xuICAgICAgICAgICAgbCA9IGJlemxlbih4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQsIHQyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGludGVyc2VjdCh4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTQpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgbW1heCh4MSwgeDIpIDwgbW1pbih4MywgeDQpIHx8XG4gICAgICAgICAgICBtbWluKHgxLCB4MikgPiBtbWF4KHgzLCB4NCkgfHxcbiAgICAgICAgICAgIG1tYXgoeTEsIHkyKSA8IG1taW4oeTMsIHk0KSB8fFxuICAgICAgICAgICAgbW1pbih5MSwgeTIpID4gbW1heCh5MywgeTQpXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBueCA9ICh4MSAqIHkyIC0geTEgKiB4MikgKiAoeDMgLSB4NCkgLSAoeDEgLSB4MikgKiAoeDMgKiB5NCAtIHkzICogeDQpLFxuICAgICAgICAgICAgbnkgPSAoeDEgKiB5MiAtIHkxICogeDIpICogKHkzIC0geTQpIC0gKHkxIC0geTIpICogKHgzICogeTQgLSB5MyAqIHg0KSxcbiAgICAgICAgICAgIGRlbm9taW5hdG9yID0gKHgxIC0geDIpICogKHkzIC0geTQpIC0gKHkxIC0geTIpICogKHgzIC0geDQpO1xuXG4gICAgICAgIGlmICghZGVub21pbmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgcHggPSBueCAvIGRlbm9taW5hdG9yLFxuICAgICAgICAgICAgcHkgPSBueSAvIGRlbm9taW5hdG9yLFxuICAgICAgICAgICAgcHgyID0gK3B4LnRvRml4ZWQoMiksXG4gICAgICAgICAgICBweTIgPSArcHkudG9GaXhlZCgyKTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgcHgyIDwgK21taW4oeDEsIHgyKS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweDIgPiArbW1heCh4MSwgeDIpLnRvRml4ZWQoMikgfHxcbiAgICAgICAgICAgIHB4MiA8ICttbWluKHgzLCB4NCkudG9GaXhlZCgyKSB8fFxuICAgICAgICAgICAgcHgyID4gK21tYXgoeDMsIHg0KS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweTIgPCArbW1pbih5MSwgeTIpLnRvRml4ZWQoMikgfHxcbiAgICAgICAgICAgIHB5MiA+ICttbWF4KHkxLCB5MikudG9GaXhlZCgyKSB8fFxuICAgICAgICAgICAgcHkyIDwgK21taW4oeTMsIHk0KS50b0ZpeGVkKDIpIHx8XG4gICAgICAgICAgICBweTIgPiArbW1heCh5MywgeTQpLnRvRml4ZWQoMilcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHt4OiBweCwgeTogcHl9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnRlcihiZXoxLCBiZXoyKSB7XG4gICAgICAgIHJldHVybiBpbnRlckhlbHBlcihiZXoxLCBiZXoyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW50ZXJDb3VudChiZXoxLCBiZXoyKSB7XG4gICAgICAgIHJldHVybiBpbnRlckhlbHBlcihiZXoxLCBiZXoyLCAxKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW50ZXJIZWxwZXIoYmV6MSwgYmV6MiwganVzdENvdW50KSB7XG4gICAgICAgIHZhciBiYm94MSA9IFIuYmV6aWVyQkJveChiZXoxKSxcbiAgICAgICAgICAgIGJib3gyID0gUi5iZXppZXJCQm94KGJlejIpO1xuICAgICAgICBpZiAoIVIuaXNCQm94SW50ZXJzZWN0KGJib3gxLCBiYm94MikpIHtcbiAgICAgICAgICAgIHJldHVybiBqdXN0Q291bnQgPyAwIDogW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGwxID0gYmV6bGVuLmFwcGx5KDAsIGJlejEpLFxuICAgICAgICAgICAgbDIgPSBiZXpsZW4uYXBwbHkoMCwgYmV6MiksXG4gICAgICAgICAgICBuMSA9IG1tYXgofn4obDEgLyA1KSwgMSksXG4gICAgICAgICAgICBuMiA9IG1tYXgofn4obDIgLyA1KSwgMSksXG4gICAgICAgICAgICBkb3RzMSA9IFtdLFxuICAgICAgICAgICAgZG90czIgPSBbXSxcbiAgICAgICAgICAgIHh5ID0ge30sXG4gICAgICAgICAgICByZXMgPSBqdXN0Q291bnQgPyAwIDogW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjEgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwID0gUi5maW5kRG90c0F0U2VnbWVudC5hcHBseShSLCBiZXoxLmNvbmNhdChpIC8gbjEpKTtcbiAgICAgICAgICAgIGRvdHMxLnB1c2goe3g6IHAueCwgeTogcC55LCB0OiBpIC8gbjF9KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbjIgKyAxOyBpKyspIHtcbiAgICAgICAgICAgIHAgPSBSLmZpbmREb3RzQXRTZWdtZW50LmFwcGx5KFIsIGJlejIuY29uY2F0KGkgLyBuMikpO1xuICAgICAgICAgICAgZG90czIucHVzaCh7eDogcC54LCB5OiBwLnksIHQ6IGkgLyBuMn0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBuMTsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG4yOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZGkgPSBkb3RzMVtpXSxcbiAgICAgICAgICAgICAgICAgICAgZGkxID0gZG90czFbaSArIDFdLFxuICAgICAgICAgICAgICAgICAgICBkaiA9IGRvdHMyW2pdLFxuICAgICAgICAgICAgICAgICAgICBkajEgPSBkb3RzMltqICsgMV0sXG4gICAgICAgICAgICAgICAgICAgIGNpID0gYWJzKGRpMS54IC0gZGkueCkgPCAuMDAxID8gXCJ5XCIgOiBcInhcIixcbiAgICAgICAgICAgICAgICAgICAgY2ogPSBhYnMoZGoxLnggLSBkai54KSA8IC4wMDEgPyBcInlcIiA6IFwieFwiLFxuICAgICAgICAgICAgICAgICAgICBpcyA9IGludGVyc2VjdChkaS54LCBkaS55LCBkaTEueCwgZGkxLnksIGRqLngsIGRqLnksIGRqMS54LCBkajEueSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh4eVtpcy54LnRvRml4ZWQoNCldID09IGlzLnkudG9GaXhlZCg0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgeHlbaXMueC50b0ZpeGVkKDQpXSA9IGlzLnkudG9GaXhlZCg0KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHQxID0gZGkudCArIGFicygoaXNbY2ldIC0gZGlbY2ldKSAvIChkaTFbY2ldIC0gZGlbY2ldKSkgKiAoZGkxLnQgLSBkaS50KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHQyID0gZGoudCArIGFicygoaXNbY2pdIC0gZGpbY2pdKSAvIChkajFbY2pdIC0gZGpbY2pdKSkgKiAoZGoxLnQgLSBkai50KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQxID49IDAgJiYgdDEgPD0gMS4wMDEgJiYgdDIgPj0gMCAmJiB0MiA8PSAxLjAwMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGp1c3RDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg6IGlzLngsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk6IGlzLnksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQxOiBtbWluKHQxLCAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdDI6IG1taW4odDIsIDEpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwucGF0aEludGVyc2VjdGlvblxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBGaW5kcyBpbnRlcnNlY3Rpb25zIG9mIHR3byBwYXRoc1xuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBwYXRoMSAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAtIHBhdGgyIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgID0gKGFycmF5KSBkb3RzIG9mIGludGVyc2VjdGlvblxuICAgICBvIFtcbiAgICAgbyAgICAge1xuICAgICBvICAgICAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICAgICAgeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxuICAgICBvICAgICAgICAgdDE6IChudW1iZXIpIHQgdmFsdWUgZm9yIHNlZ21lbnQgb2YgcGF0aDFcbiAgICAgbyAgICAgICAgIHQyOiAobnVtYmVyKSB0IHZhbHVlIGZvciBzZWdtZW50IG9mIHBhdGgyXG4gICAgIG8gICAgICAgICBzZWdtZW50MTogKG51bWJlcikgb3JkZXIgbnVtYmVyIGZvciBzZWdtZW50IG9mIHBhdGgxXG4gICAgIG8gICAgICAgICBzZWdtZW50MjogKG51bWJlcikgb3JkZXIgbnVtYmVyIGZvciBzZWdtZW50IG9mIHBhdGgyXG4gICAgIG8gICAgICAgICBiZXoxOiAoYXJyYXkpIGVpZ2h0IGNvb3JkaW5hdGVzIHJlcHJlc2VudGluZyBiZXppw6lyIGN1cnZlIGZvciB0aGUgc2VnbWVudCBvZiBwYXRoMVxuICAgICBvICAgICAgICAgYmV6MjogKGFycmF5KSBlaWdodCBjb29yZGluYXRlcyByZXByZXNlbnRpbmcgYmV6acOpciBjdXJ2ZSBmb3IgdGhlIHNlZ21lbnQgb2YgcGF0aDJcbiAgICAgbyAgICAgfVxuICAgICBvIF1cbiAgICBcXCovXG4gICAgUi5wYXRoSW50ZXJzZWN0aW9uID0gZnVuY3Rpb24gKHBhdGgxLCBwYXRoMikge1xuICAgICAgICByZXR1cm4gaW50ZXJQYXRoSGVscGVyKHBhdGgxLCBwYXRoMik7XG4gICAgfTtcbiAgICBSLnBhdGhJbnRlcnNlY3Rpb25OdW1iZXIgPSBmdW5jdGlvbiAocGF0aDEsIHBhdGgyKSB7XG4gICAgICAgIHJldHVybiBpbnRlclBhdGhIZWxwZXIocGF0aDEsIHBhdGgyLCAxKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIGludGVyUGF0aEhlbHBlcihwYXRoMSwgcGF0aDIsIGp1c3RDb3VudCkge1xuICAgICAgICBwYXRoMSA9IFIuX3BhdGgyY3VydmUocGF0aDEpO1xuICAgICAgICBwYXRoMiA9IFIuX3BhdGgyY3VydmUocGF0aDIpO1xuICAgICAgICB2Y
57590XIgeDEsIHkxLCB4MiwgeTIsIHgxbSwgeTFtLCB4Mm0sIHkybSwgYmV6MSwgYmV6MixcbiAgICAgICAgICAgIHJlcyA9IGp1c3RDb3VudCA/IDAgOiBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcGF0aDEubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBpID0gcGF0aDFbaV07XG4gICAgICAgICAgICBpZiAocGlbMF0gPT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICB4MSA9IHgxbSA9IHBpWzFdO1xuICAgICAgICAgICAgICAgIHkxID0geTFtID0gcGlbMl07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChwaVswXSA9PSBcIkNcIikge1xuICAgICAgICAgICAgICAgICAgICBiZXoxID0gW3gxLCB5MV0uY29uY2F0KHBpLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgeDEgPSBiZXoxWzZdO1xuICAgICAgICAgICAgICAgICAgICB5MSA9IGJlejFbN107XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYmV6MSA9IFt4MSwgeTEsIHgxLCB5MSwgeDFtLCB5MW0sIHgxbSwgeTFtXTtcbiAgICAgICAgICAgICAgICAgICAgeDEgPSB4MW07XG4gICAgICAgICAgICAgICAgICAgIHkxID0geTFtO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBwYXRoMi5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwaiA9IHBhdGgyW2pdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGpbMF0gPT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHgyID0geDJtID0gcGpbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB5MiA9IHkybSA9IHBqWzJdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBqWzBdID09IFwiQ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV6MiA9IFt4MiwgeTJdLmNvbmNhdChwai5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeDIgPSBiZXoyWzZdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gYmV6Mls3XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV6MiA9IFt4MiwgeTIsIHgyLCB5MiwgeDJtLCB5Mm0sIHgybSwgeTJtXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IHgybTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5MiA9IHkybTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnRyID0gaW50ZXJIZWxwZXIoYmV6MSwgYmV6MiwganVzdENvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChqdXN0Q291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMgKz0gaW50cjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDAsIGtrID0gaW50ci5sZW5ndGg7IGsgPCBrazsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludHJba10uc2VnbWVudDEgPSBpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRyW2tdLnNlZ21lbnQyID0gajtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50cltrXS5iZXoxID0gYmV6MTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50cltrXS5iZXoyID0gYmV6MjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzLmNvbmNhdChpbnRyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5pc1BvaW50SW5zaWRlUGF0aFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGB0cnVlYCBpZiBnaXZlbiBwb2ludCBpcyBpbnNpZGUgYSBnaXZlbiBjbG9zZWQgcGF0aC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcGF0aCAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAtIHggKG51bWJlcikgeCBvZiB0aGUgcG9pbnRcbiAgICAgLSB5IChudW1iZXIpIHkgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIHRydWUsIGlmIHBvaW50IGlzIGluc2lkZSB0aGUgcGF0aFxuICAgIFxcKi9cbiAgICBSLmlzUG9pbnRJbnNpZGVQYXRoID0gZnVuY3Rpb24gKHBhdGgsIHgsIHkpIHtcbiAgICAgICAgdmFyIGJib3ggPSBSLnBhdGhCQm94KHBhdGgpO1xuICAgICAgICByZXR1cm4gUi5pc1BvaW50SW5zaWRlQkJveChiYm94LCB4LCB5KSAmJlxuICAgICAgICAgICAgICAgaW50ZXJQYXRoSGVscGVyKHBhdGgsIFtbXCJNXCIsIHgsIHldLCBbXCJIXCIsIGJib3gueDIgKyAxMF1dLCAxKSAlIDIgPT0gMTtcbiAgICB9O1xuICAgIFIuX3JlbW92ZWRGYWN0b3J5ID0gZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwubG9nXCIsIG51bGwsIFwiUmFwaGFcXHhlYmw6IHlvdSBhcmUgY2FsbGluZyB0byBtZXRob2QgXFx1MjAxY1wiICsgbWV0aG9kbmFtZSArIFwiXFx1MjAxZCBvZiByZW1vdmVkIG9iamVjdFwiLCBtZXRob2RuYW1lKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLnBhdGhCQm94XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIFJldHVybiBib3VuZGluZyBib3ggb2YgYSBnaXZlbiBwYXRoXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGggKHN0cmluZykgcGF0aCBzdHJpbmdcbiAgICAgPSAob2JqZWN0KSBib3VuZGluZyBib3hcbiAgICAgbyB7XG4gICAgIG8gICAgIHg6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgbGVmdCB0b3AgcG9pbnQgb2YgdGhlIGJveFxuICAgICBvICAgICB5OiAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGxlZnQgdG9wIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgeDI6IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYm90dG9tIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgeTI6IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcmlnaHQgYm90dG9tIHBvaW50IG9mIHRoZSBib3hcbiAgICAgbyAgICAgd2lkdGg6IChudW1iZXIpIHdpZHRoIG9mIHRoZSBib3hcbiAgICAgbyAgICAgaGVpZ2h0OiAobnVtYmVyKSBoZWlnaHQgb2YgdGhlIGJveFxuICAgICBvICAgICBjeDogKG51bWJlcikgeCBjb29yZGluYX
57590RlIG9mIHRoZSBjZW50ZXIgb2YgdGhlIGJveFxuICAgICBvICAgICBjeTogKG51bWJlcikgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50ZXIgb2YgdGhlIGJveFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgdmFyIHBhdGhEaW1lbnNpb25zID0gUi5wYXRoQkJveCA9IGZ1bmN0aW9uIChwYXRoKSB7XG4gICAgICAgIHZhciBwdGggPSBwYXRocyhwYXRoKTtcbiAgICAgICAgaWYgKHB0aC5iYm94KSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvbmUocHRoLmJib3gpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHt4OiAwLCB5OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwLCB4MjogMCwgeTI6IDB9O1xuICAgICAgICB9XG4gICAgICAgIHBhdGggPSBwYXRoMmN1cnZlKHBhdGgpO1xuICAgICAgICB2YXIgeCA9IDAsXG4gICAgICAgICAgICB5ID0gMCxcbiAgICAgICAgICAgIFggPSBbXSxcbiAgICAgICAgICAgIFkgPSBbXSxcbiAgICAgICAgICAgIHA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHBhdGgubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgcCA9IHBhdGhbaV07XG4gICAgICAgICAgICBpZiAocFswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgIHggPSBwWzFdO1xuICAgICAgICAgICAgICAgIHkgPSBwWzJdO1xuICAgICAgICAgICAgICAgIFgucHVzaCh4KTtcbiAgICAgICAgICAgICAgICBZLnB1c2goeSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBkaW0gPSBjdXJ2ZURpbSh4LCB5LCBwWzFdLCBwWzJdLCBwWzNdLCBwWzRdLCBwWzVdLCBwWzZdKTtcbiAgICAgICAgICAgICAgICBYID0gWFtjb25jYXRdKGRpbS5taW4ueCwgZGltLm1heC54KTtcbiAgICAgICAgICAgICAgICBZID0gWVtjb25jYXRdKGRpbS5taW4ueSwgZGltLm1heC55KTtcbiAgICAgICAgICAgICAgICB4ID0gcFs1XTtcbiAgICAgICAgICAgICAgICB5ID0gcFs2XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgeG1pbiA9IG1taW5bYXBwbHldKDAsIFgpLFxuICAgICAgICAgICAgeW1pbiA9IG1taW5bYXBwbHldKDAsIFkpLFxuICAgICAgICAgICAgeG1heCA9IG1tYXhbYXBwbHldKDAsIFgpLFxuICAgICAgICAgICAgeW1heCA9IG1tYXhbYXBwbHldKDAsIFkpLFxuICAgICAgICAgICAgd2lkdGggPSB4bWF4IC0geG1pbixcbiAgICAgICAgICAgIGhlaWdodCA9IHltYXggLSB5bWluLFxuICAgICAgICAgICAgICAgIGJiID0ge1xuICAgICAgICAgICAgICAgIHg6IHhtaW4sXG4gICAgICAgICAgICAgICAgeTogeW1pbixcbiAgICAgICAgICAgICAgICB4MjogeG1heCxcbiAgICAgICAgICAgICAgICB5MjogeW1heCxcbiAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgY3g6IHhtaW4gKyB3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgY3k6IHltaW4gKyBoZWlnaHQgLyAyXG4gICAgICAgICAgICB9O1xuICAgICAgICBwdGguYmJveCA9IGNsb25lKGJiKTtcbiAgICAgICAgcmV0dXJuIGJiO1xuICAgIH0sXG4gICAgICAgIHBhdGhDbG9uZSA9IGZ1bmN0aW9uIChwYXRoQXJyYXkpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBjbG9uZShwYXRoQXJyYXkpO1xuICAgICAgICAgICAgcmVzLnRvU3RyaW5nID0gUi5fcGF0aDJzdHJpbmc7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9LFxuICAgICAgICBwYXRoVG9SZWxhdGl2ZSA9IFIuX3BhdGhUb1JlbGF0aXZlID0gZnVuY3Rpb24gKHBhdGhBcnJheSkge1xuICAgICAgICAgICAgdmFyIHB0aCA9IHBhdGhzKHBhdGhBcnJheSk7XG4gICAgICAgICAgICBpZiAocHRoLnJlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoQ2xvbmUocHRoLnJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIVIuaXMocGF0aEFycmF5LCBhcnJheSkgfHwgIVIuaXMocGF0aEFycmF5ICYmIHBhdGhBcnJheVswXSwgYXJyYXkpKSB7IC8vIHJvdWdoIGFzc3VtcHRpb25cbiAgICAgICAgICAgICAgICBwYXRoQXJyYXkgPSBSLnBhcnNlUGF0aFN0cmluZyhwYXRoQXJyYXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlcyA9IFtdLFxuICAgICAgICAgICAgICAgIHggPSAwLFxuICAgICAgICAgICAgICAgIHkgPSAwLFxuICAgICAgICAgICAgICAgIG14ID0gMCxcbiAgICAgICAgICAgICAgICBteSA9IDAsXG4gICAgICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICAgICAgaWYgKHBhdGhBcnJheVswXVswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgIHggPSBwYXRoQXJyYXlbMF1bMV07XG4gICAgICAgICAgICAgICAgeSA9IHBhdGhBcnJheVswXVsyXTtcbiAgICAgICAgICAgICAgICBteCA9IHg7XG4gICAgICAgICAgICAgICAgbXkgPSB5O1xuICAgICAgICAgICAgICAgIHN0YXJ0Kys7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goW1wiTVwiLCB4LCB5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gc3RhcnQsIGlpID0gcGF0aEFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgciA9IHJlc1tpXSA9IFtdLFxuICAgICAgICAgICAgICAgICAgICBwYSA9IHBhdGhBcnJheVtpXTtcbiAgICAgICAgICAgICAgICBpZiAocGFbMF0gIT0gbG93ZXJDYXNlLmNhbGwocGFbMF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJbMF0gPSBsb3dlckNhc2UuY2FsbChwYVswXSk7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoclswXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzFdID0gcGFbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclsyXSA9IHBhWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbM10gPSBwYVszXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzRdID0gcGFbNF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcls1XSA9IHBhWzVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbNl0gPSArKHBhWzZdIC0geCkudG9GaXhlZCgzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzddID0gKyhwYVs3XSAtIHkpLnRvRml4ZWQoMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbMV0gPSArKHBhWzFdIC0geSkudG9GaXhlZCgzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJtXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSBwYVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBteSA9IHBhWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMSwgamogPSBwYS5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbal0gPSArKHBhW2pdIC0gKChqICUgMikgPyB4IDogeSkpLnRvRml4ZWQoMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgciA9IHJlc1tpXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFbMF0gPT0gXCJtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG14ID0gcGFbMV0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgbXkgPSBwYVsyXSArIHk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDAsIGtrID0gcGEubGVuZ3RoOyBrIDwga2s7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzW2ldW2tdID0gcGFba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IHJlc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyZXNbaV1bMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInpcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBteDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBteTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgeCArPSArcmVzW2ldW2xlbiAtIDFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB5ICs9ICtyZXNbaV1bbGVuIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggKz0gK3Jlc1tpXVtsZW4gLSAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgKz0gK3Jlc1tpXVtsZW4gLSAxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMudG9TdHJpbmcgPSBSLl9wYXR
57590oMnN0cmluZztcbiAgICAgICAgICAgIHB0aC5yZWwgPSBwYXRoQ2xvbmUocmVzKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0sXG4gICAgICAgIHBhdGhUb0Fic29sdXRlID0gUi5fcGF0aFRvQWJzb2x1dGUgPSBmdW5jdGlvbiAocGF0aEFycmF5KSB7XG4gICAgICAgICAgICB2YXIgcHRoID0gcGF0aHMocGF0aEFycmF5KTtcbiAgICAgICAgICAgIGlmIChwdGguYWJzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguYWJzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghUi5pcyhwYXRoQXJyYXksIGFycmF5KSB8fCAhUi5pcyhwYXRoQXJyYXkgJiYgcGF0aEFycmF5WzBdLCBhcnJheSkpIHsgLy8gcm91Z2ggYXNzdW1wdGlvblxuICAgICAgICAgICAgICAgIHBhdGhBcnJheSA9IFIucGFyc2VQYXRoU3RyaW5nKHBhdGhBcnJheSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBhdGhBcnJheSB8fCAhcGF0aEFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbW1wiTVwiLCAwLCAwXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVzID0gW10sXG4gICAgICAgICAgICAgICAgeCA9IDAsXG4gICAgICAgICAgICAgICAgeSA9IDAsXG4gICAgICAgICAgICAgICAgbXggPSAwLFxuICAgICAgICAgICAgICAgIG15ID0gMCxcbiAgICAgICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgICAgICBpZiAocGF0aEFycmF5WzBdWzBdID09IFwiTVwiKSB7XG4gICAgICAgICAgICAgICAgeCA9ICtwYXRoQXJyYXlbMF1bMV07XG4gICAgICAgICAgICAgICAgeSA9ICtwYXRoQXJyYXlbMF1bMl07XG4gICAgICAgICAgICAgICAgbXggPSB4O1xuICAgICAgICAgICAgICAgIG15ID0geTtcbiAgICAgICAgICAgICAgICBzdGFydCsrO1xuICAgICAgICAgICAgICAgIHJlc1swXSA9IFtcIk1cIiwgeCwgeV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2Y
57590XIgY3J6ID0gcGF0aEFycmF5Lmxlbmd0aCA9PSAzICYmIHBhdGhBcnJheVswXVswXSA9PSBcIk1cIiAmJiBwYXRoQXJyYXlbMV1bMF0udG9VcHBlckNhc2UoKSA9PSBcIlJcIiAmJiBwYXRoQXJyYXlbMl1bMF0udG9VcHBlckNhc2UoKSA9PSBcIlpcIjtcbiAgICAgICAgICAgIGZvciAodmFyIHIsIHBhLCBpID0gc3RhcnQsIGlpID0gcGF0aEFycmF5Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChyID0gW10pO1xuICAgICAgICAgICAgICAgIHBhID0gcGF0aEFycmF5W2ldO1xuICAgICAgICAgICAgICAgIGlmIChwYVswXSAhPSB1cHBlckNhc2UuY2FsbChwYVswXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgclswXSA9IHVwcGVyQ2FzZS5jYWxsKHBhWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiQVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbMV0gPSBwYVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzJdID0gcGFbMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclszXSA9IHBhWzNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbNF0gPSBwYVs0XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzVdID0gcGFbNV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcls2XSA9ICsocGFbNl0gKyB4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzddID0gKyhwYVs3XSArIHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlZcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzFdID0gK3BhWzFdICsgeTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJIXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgclsxXSA9ICtwYVsxXSArIHg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiUlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkb3RzID0gW3gsIHldW2NvbmNhdF0ocGEuc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAyLCBqaiA9IGRvdHMubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3RzW2pdID0gK2RvdHNbal0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3RzWysral0gPSArZG90c1tqXSArIHk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMgPSByZXNbY29uY2F0XShjYXRtdWxsUm9tMmJlemllcihkb3RzLCBjcnopKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXggPSArcGFbMV0gKyB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG15ID0gK3BhWzJdICsgeTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMSwgamogPSBwYS5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbal0gPSArcGFbal0gKyAoKGogJSAyKSA/IHggOiB5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhWzBdID09IFwiUlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvdHMgPSBbeCwgeV1bY29uY2F0XShwYS5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzW2NvbmNhdF0oY2F0bXVsbFJvbTJiZXppZXIoZG90cywgY3J6KSk7XG4gICAgICAgICAgICAgICAgICAgIHIgPSBbXCJSXCJdW2NvbmNhdF0ocGEuc2xpY2UoLTIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMCwga2sgPSBwYS5sZW5ndGg7IGsgPCBrazsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByW2tdID0gcGFba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3dpdGNoIChyWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB4ID0gbXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gbXk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkhcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSByWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJWXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gclsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiTVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbXggPSByW3IubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICAgICAgICAgICAgICBteSA9IHJbci5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSByW3IubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICAgICAgICAgICAgICB5ID0gcltyLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy50b1N0cmluZyA9IFIuX3BhdGgyc3RyaW5nO1xuICAgICAgICAgICAgcHRoLmFicyA9IHBhdGhDbG9uZShyZXMpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSxcbiAgICAgICAgbDJjID0gZnVuY3Rpb24gKHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgICAgICByZXR1cm4gW3gxLCB5MSwgeDIsIHkyLCB4MiwgeTJdO1xuICAgICAgICB9LFxuICAgICAgICBxMmMgPSBmdW5jdGlvbiAoeDEsIHkxLCBheCwgYXksIHgyLCB5Mikge1xuICAgICAgICAgICAgdmFyIF8xMyA9IDEgLyAzLFxuICAgICAgICAgICAgICAgIF8yMyA9IDIgLyAzO1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeDEgKyBfMjMgKiBheCxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeTEgKyBfMjMgKiBheSxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeDIgKyBfMjMgKiBheCxcbiAgICAgICAgICAgICAgICAgICAgXzEzICogeTIgKyBfMjMgKiBheSxcbiAgICAgICAgICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICAgICAgICAgI
57590HkyXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgfSxcbiAgICAgICAgYTJjID0gZnVuY3Rpb24gKHgxLCB5MSwgcngsIHJ5LCBhbmdsZSwgbGFyZ2VfYXJjX2ZsYWcsIHN3ZWVwX2ZsYWcsIHgyLCB5MiwgcmVjdXJzaXZlKSB7XG4gICAgICAgICAgICAvLyBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvZiB3aGVyZSB0aGlzIG1hdGggY2FtZSBmcm9tIHZpc2l0OlxuICAgICAgICAgICAgLy8gaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvaW1wbG5vdGUuaHRtbCNBcmNJbXBsZW1lbnRhdGlvbk5vdGVzXG4gICAgICAgICAgICB2YXIgXzEyMCA9IFBJICogMTIwIC8gMTgwLFxuICAgICAgICAgICAgICAgIHJhZCA9IFBJIC8gMTgwICogKCthbmdsZSB8fCAwKSxcbiAgICAgICAgICAgICAgICByZXMgPSBbXSxcbiAgICAgICAgICAgICAgICB4eSxcbiAgICAgICAgICAgICAgICByb3RhdGUgPSBjYWNoZXIoZnVuY3Rpb24gKHgsIHksIHJhZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgWCA9IHggKiBtYXRoLmNvcyhyYWQpIC0geSAqIG1hdGguc2luKHJhZCksXG4gICAgICAgICAgICAgICAgICAgICAgICBZID0geCAqIG1hdGguc2luKHJhZCkgKyB5ICogbWF0aC5jb3MocmFkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt4OiBYLCB5OiBZfTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghcmVjdXJzaXZlKSB7XG4gICAgICAgICAgICAgICAgeHkgPSByb3RhdGUoeDEsIHkxLCAtcmFkKTtcbiAgICAgICAgICAgICAgICB4MSA9IHh5Lng7XG4gICAgICAgICAgICAgICAgeTEgPSB4eS55O1xuICAgICAgICAgICAgICAgIHh5ID0gcm90YXRlKHgyLCB5MiwgLXJhZCk7XG4gICAgICAgICAgICAgICAgeDIgPSB4eS54O1xuICAgICAgICAgICAgICAgIHkyID0geHkueTtcbiAgICAgICAgICAgICAgICB2Y
57590XIgY29zID0gbWF0aC5jb3MoUEkgLyAxODAgKiBhbmdsZSksXG4gICAgICAgICAgICAgICAgICAgIHNpbiA9IG1hdGguc2luKFBJIC8gMTgwICogYW5nbGUpLFxuICAgICAgICAgICAgICAgICAgICB4ID0gKHgxIC0geDIpIC8gMixcbiAgICAgICAgICAgICAgICAgICAgeSA9ICh5MSAtIHkyKSAvIDI7XG4gICAgICAgICAgICAgICAgdmFyIGggPSAoeCAqIHgpIC8gKHJ4ICogcngpICsgKHkgKiB5KSAvIChyeSAqIHJ5KTtcbiAgICAgICAgICAgICAgICBpZiAoaCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaCA9IG1hdGguc3FydChoKTtcbiAgICAgICAgICAgICAgICAgICAgcnggPSBoICogcng7XG4gICAgICAgICAgICAgICAgICAgIHJ5ID0gaCAqIHJ5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcngyID0gcnggKiByeCxcbiAgICAgICAgICAgICAgICAgICAgcnkyID0gcnkgKiByeSxcbiAgICAgICAgICAgICAgICAgICAgayA9IChsYXJnZV9hcmNfZmxhZyA9PSBzd2VlcF9mbGFnID8gLTEgOiAxKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRoLnNxcnQoYWJzKChyeDIgKiByeTIgLSByeDIgKiB5ICogeSAtIHJ5MiAqIHggKiB4KSAvIChyeDIgKiB5ICogeSArIHJ5MiAqIHggKiB4KSkpLFxuICAgICAgICAgICAgICAgICAgICBjeCA9IGsgKiByeCAqIHkgLyByeSArICh4MSArIHgyKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIGN5ID0gayAqIC1yeSAqIHggLyByeCArICh5MSArIHkyKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIGYxID0gbWF0aC5hc2luKCgoeTEgLSBjeSkgLyByeSkudG9GaXhlZCg5KSksXG4gICAgICAgICAgICAgICAgICAgIGYyID0gbWF0aC5hc2luKCgoeTIgLSBjeSkgLyByeSkudG9GaXhlZCg5KSk7XG5cbiAgICAgICAgICAgICAgICBmMSA9IHgxIDwgY3ggPyBQSSAtIGYxIDogZjE7XG4gICAgICAgICAgICAgICAgZjIgPSB4MiA8IGN4ID8gUEkgLSBmMiA6IGYyO1xuICAgICAgICAgICAgICAgIGYxIDwgMCAmJiAoZjEgPSBQSSAqIDIgKyBmMSk7XG4gICAgICAgICAgICAgICAgZjIgPCAwICYmIChmMiA9IFBJICogMiArIGYyKTtcbiAgICAgICAgICAgICAgICBpZiAoc3dlZXBfZmxhZyAmJiBmMSA+IGYyKSB7XG4gICAgICAgICAgICAgICAgICAgIGYxID0gZjEgLSBQSSAqIDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghc3dlZXBfZmxhZyAmJiBmMiA+IGYxKSB7XG4gICAgICAgICAgICAgICAgICAgIGYyID0gZjIgLSBQSSAqIDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmMSA9IHJlY3Vyc2l2ZVswXTtcbiAgICAgICAgICAgICAgICBmMiA9IHJlY3Vyc2l2ZVsxXTtcbiAgICAgICAgICAgICAgICBjeCA9IHJlY3Vyc2l2ZVsyXTtcbiAgICAgICAgICAgICAgICBjeSA9IHJlY3Vyc2l2ZVszXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkZiA9IGYyIC0gZjE7XG4gICAgICAgICAgICBpZiAoYWJzKGRmKSA+IF8xMjApIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZjJvbGQgPSBmMixcbiAgICAgICAgICAgICAgICAgICAgeDJvbGQgPSB4MixcbiAgICAgICAgICAgICAgICAgICAgeTJvbGQgPSB5MjtcbiAgICAgICAgICAgICAgICBmMiA9IGYxICsgXzEyMCAqIChzd2VlcF9mbGFnICYmIGYyID4gZjEgPyAxIDogLTEpO1xuICAgICAgICAgICAgICAgIHgyID0gY3ggKyByeCAqIG1hdGguY29zKGYyKTtcbiAgICAgICAgICAgICAgICB5MiA9IGN5ICsgcnkgKiBtYXRoLnNpbihmMik7XG4gICAgICAgICAgICAgICAgcmVzID0gYTJjKHgyLCB5MiwgcngsIHJ5LCBhbmdsZSwgMCwgc3dlZXBfZmxhZywgeDJvbGQsIHkyb2xkLCBbZjIsIGYyb2xkLCBjeCwgY3ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRmID0gZjIgLSBmMTtcbiAgICAgICAgICAgIHZhciBjMSA9IG1hdGguY29zKGYxKSxcbiAgICAgICAgICAgICAgICBzMSA9IG1hdGguc2luKGYxKSxcbiAgICAgICAgICAgICAgICBjMiA9IG1hdGguY29zKGYyKSxcbiAgICAgICAgICAgICAgICBzMiA9IG1hdGguc2luKGYyKSxcbiAgICAgICAgICAgICAgICB0ID0gbWF0aC50YW4oZGYgLyA0KSxcbiAgICAgICAgICAgICAgICBoeCA9IDQgLyAzICogcnggKiB0LFxuICAgICAgICAgICAgICAgIGh5ID0gNCAvIDMgKiByeSAqIHQsXG4gICAgICAgICAgICAgICAgbTEgPSBbeDEsIHkxXSxcbiAgICAgICAgICAgICAgICBtMiA9IFt4MSArIGh4ICogczEsIHkxIC0gaHkgKiBjMV0sXG4gICAgICAgICAgICAgICAgbTMgPSBbeDIgKyBoeCAqIHMyLCB5MiAtIGh5ICogYzJdLFxuICAgICAgICAgICAgICAgIG00ID0gW3gyLCB5Ml07XG4gICAgICAgICAgICBtMlswXSA9IDIgKiBtMVswXSAtIG0yWzBdO1xuICAgICAgICAgICAgbTJbMV0gPSAyICogbTFbMV0gLSBtMlsxXTtcbiAgICAgICAgICAgIGlmIChyZWN1cnNpdmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW20yLCBtMywgbTRdW2NvbmNhdF0ocmVzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzID0gW20yLCBtMywgbTRdW2NvbmNhdF0ocmVzKS5qb2luKClbc3BsaXRdKFwiLFwiKTtcbiAgICAgICAgICAgICAgICB2Y
57590XIgbmV3cmVzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3cmVzW2ldID0gaSAlIDIgPyByb3RhdGUocmVzW2kgLSAxXSwgcmVzW2ldLCByYWQpLnkgOiByb3RhdGUocmVzW2ldLCByZXNbaSArIDFdLCByYWQpLng7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdyZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGZpbmREb3RBdFNlZ21lbnQgPSBmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQpIHtcbiAgICAgICAgICAgIHZhciB0MSA9IDEgLSB0O1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiBwb3codDEsIDMpICogcDF4ICsgcG93KHQxLCAyKSAqIDMgKiB0ICogYzF4ICsgdDEgKiAzICogdCAqIHQgKiBjMnggKyBwb3codCwgMykgKiBwMngsXG4gICAgICAgICAgICAgICAgeTogcG93KHQxLCAzKSAqIHAxeSArIHBvdyh0MSwgMikgKiAzICogdCAqIGMxeSArIHQxICogMyAqIHQgKiB0ICogYzJ5ICsgcG93KHQsIDMpICogcDJ5XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBjdXJ2ZURpbSA9IGNhY2hlcihmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnkpIHtcbiAgICAgICAgICAgIHZhciBhID0gKGMyeCAtIDIgKiBjMXggKyBwMXgpIC0gKHAyeCAtIDIgKiBjMnggKyBjMXgpLFxuICAgICAgICAgICAgICAgIGIgPSAyICogKGMxeCAtIHAxeCkgLSAyICogKGMyeCAtIGMxeCksXG4gICAgICAgICAgICAgICAgYyA9IHAxeCAtIGMxeCxcbiAgICAgICAgICAgICAgICB0MSA9ICgtYiArIG1hdGguc3FydChiICogYiAtIDQgKiBhICogYykpIC8gMiAvIGEsXG4gICAgICAgICAgICAgICAgdDIgPSAoLWIgLSBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhLFxuICAgICAgICAgICAgICAgIHkgPSBbcDF5LCBwMnldLFxuICAgICAgICAgICAgICAgIHggPSBbcDF4LCBwMnhdLFxuICAgICAgICAgICAgICAgIGRvdDtcbiAgICAgICAgICAgIGFicyh0MSkgPiBcIjFlMTJcIiAmJiAodDEgPSAuNSk7XG4gICAgICAgICAgICBhYnModDIpID4gXCIxZTEyXCIgJiYgKHQyID0gLjUpO1xuICAgICAgICAgICAgaWYgKHQxID4gMCAmJiB0MSA8IDEpIHtcbiAgICAgICAgICAgICAgICBkb3QgPSBmaW5kRG90QXRTZWdtZW50KHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0MSk7XG4gICAgICAgICAgICAgICAgeC5wdXNoKGRvdC54KTtcbiAgICAgICAgICAgICAgICB5LnB1c2goZG90LnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHQyID4gMCAmJiB0MiA8IDEpIHtcbiAgICAgICAgICAgICAgICBkb3QgPSBmaW5kRG90QXRTZWdtZW50KHAxeCwgcDF5LCBjMXgsIGMxeSwgYzJ4LCBjMnksIHAyeCwgcDJ5LCB0Mik7XG4gICAgICAgICAgICAgICAgeC5wdXNoKGRvdC54KTtcbiAgICAgICAgICAgICAgICB5LnB1c2goZG90LnkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYSA9IChjMnkgLSAyICogYzF5ICsgcDF5KSAtIChwMnkgLSAyICogYzJ5ICsgYzF5KTtcbiAgICAgICAgICAgIGIgPSAyICogKGMxeSAtIHAxeSkgLSAyICogKGMyeSAtIGMxeSk7XG4gICAgICAgICAgICBjID0gcDF5IC0gYzF5O1xuICAgICAgICAgICAgdDEgPSAoLWIgKyBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhO1xuICAgICAgICAgICAgdDIgPSAoLWIgLSBtYXRoLnNxcnQoYiAqIGIgLSA0ICogYSAqIGMpKSAvIDIgLyBhO1xuICAgICAgICAgICAgYWJzKHQxKSA+IFwiMWUxMlwiICYmICh0MSA9IC41KTtcbiAgICAgICAgICAgIGFicyh0MikgPiBcIjFlMTJcIiAmJiAodDIgPSAuNSk7XG4gICAgICAgICAgICBpZiAodDEgPiAwICYmIHQxIDwgMSkge1xuICAgICAgICAgICAgICAgIGRvdCA9IGZpbmREb3RBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQxKTtcbiAgICAgICAgICAgICAgICB4LnB1c2goZG90LngpO1xuICAgICAgICAgICAgICAgIHkucHVzaChkb3QueSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodDIgPiAwICYmIHQyIDwgMSkge1xuICAgICAgICAgICAgICAgIGRvdCA9IGZpbmREb3RBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIHQyKTtcbiAgICAgICAgICAgICAgICB4LnB1c2goZG90LngpO1xuICAgICAgICAgICAgICAgIHkucHVzaChkb3QueSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG1pbjoge3g6IG1taW5bYXBwbHldKDAsIHgpLCB5OiBtbWluW2FwcGx5XSgwLCB5KX0sXG4gICAgICAgICAgICAgICAgbWF4OiB7eDogbW1heFthcHBseV0oMCwgeCksIHk6IG1tYXhbYXBwbHldKDAsIHkpfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICAgIHBhdGgyY3VydmUgPSBSLl9wYXR
57590oMmN1cnZlID0gY2FjaGVyKGZ1bmN0aW9uIChwYXRoLCBwYXRoMikge1xuICAgICAgICAgICAgdmFyIHB0aCA9ICFwYXRoMiAmJiBwYXRocyhwYXRoKTtcbiAgICAgICAgICAgIGlmICghcGF0aDIgJiYgcHRoLmN1cnZlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGhDbG9uZShwdGguY3VydmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHAgPSBwYXRoVG9BYnNvbHV0ZShwYXRoKSxcbiAgICAgICAgICAgICAgICBwMiA9IHBhdGgyICYmIHBhdGhUb0Fic29sdXRlKHBhdGgyKSxcbiAgICAgICAgICAgICAgICBhdHRycyA9IHt4OiAwLCB5OiAwLCBieDogMCwgYnk6IDAsIFg6IDAsIFk6IDAsIHF4OiBudWxsLCBxeTogbnVsbH0sXG4gICAgICAgICAgICAgICAgYXR0cnMyID0ge3g6IDAsIHk6IDAsIGJ4OiAwLCBieTogMCwgWDogMCwgWTogMCwgcXg6IG51bGwsIHF5OiBudWxsfSxcbiAgICAgICAgICAgICAgICBwcm9jZXNzUGF0aCA9IGZ1bmN0aW9uIChwYXRoLCBkLCBwY29tKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBueCwgbnksIHRxID0ge1Q6MSwgUToxfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW1wiQ1wiLCBkLngsIGQueSwgZC54LCBkLnksIGQueCwgZC55XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAhKHBhdGhbMF0gaW4gdHEpICYmIChkLnF4ID0gZC5xeSA9IG51bGwpO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHBhdGhbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZC5YID0gcGF0aFsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLlkgPSBwYXRoWzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGEyY1thcHBseV0oMCwgW2QueCwgZC55XVtjb25jYXRdKHBhdGguc2xpY2UoMSkpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiU1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwY29tID09IFwiQ1wiIHx8IHBjb20gPT0gXCJTXCIpIHsgLy8gSW4gXCJTXCIgY2FzZSB3ZSBoYXZlIHRvIHRha2UgaW50byBhY2NvdW50LCBpZiB0aGUgcHJldmlvdXMgY29tbWFuZCBpcyBDL1MuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG54ID0gZC54ICogMiAtIGQuYng7ICAgICAgICAgIC8vIEFuZCByZWZsZWN0IHRoZSBwcmV2aW91c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBueSA9IGQueSAqIDIgLSBkLmJ5OyAgICAgICAgICAvLyBjb21tYW5kJ3MgY29udHJvbCBwb2ludCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBwb2ludC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9yIHNvbWUgZWxzZSBvciBub3RoaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG54ID0gZC54O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBueSA9IGQueTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IFtcIkNcIiwgbngsIG55XVtjb25jYXRdKHBhdGguc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGNvbSA9PSBcIlFcIiB8fCBwY29tID09IFwiVFwiKSB7IC8vIEluIFwiVFwiIGNhc2Ugd2UgaGF2ZSB0byB0YWtlIGludG8gYWNjb3VudCwgaWYgdGhlIHByZXZpb3VzIGNvbW1hbmQgaXMgUS9ULlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gZC54ICogMiAtIGQucXg7ICAgICAgICAvLyBBbmQgbWFrZSBhIHJlZmxlY3Rpb24gc2ltaWxhclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gZC55ICogMiAtIGQucXk7ICAgICAgICAvLyB0byBjYXNlIFwiU1wiLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3Igc29tZXRoaW5nIGVsc2Ugb3Igbm90aGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gZC54O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gZC55O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKHEyYyhkLngsIGQueSwgZC5xeCwgZC5xeSwgcGF0aFsxXSwgcGF0aFsyXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF4ID0gcGF0aFsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnF5ID0gcGF0aFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKHEyYyhkLngsIGQueSwgcGF0aFsxXSwgcGF0aFsyXSwgcGF0aFszXSwgcGF0aFs0XSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkxcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGwyYyhkLngsIGQueSwgcGF0aFsxXSwgcGF0aFsyXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkhcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoID0gW1wiQ1wiXVtjb25jYXRdKGwyYyhkLngsIGQueSwgcGF0aFsxXSwgZC55KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiVlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgI
57590HBhdGggPSBbXCJDXCJdW2NvbmNhdF0obDJjKGQueCwgZC55LCBkLngsIHBhdGhbMV0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IFtcIkNcIl1bY29uY2F0XShsMmMoZC54LCBkLnksIGQuWCwgZC5ZKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmaXhBcmMgPSBmdW5jdGlvbiAocHAsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBwW2ldLmxlbmd0aCA+IDcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBwW2ldLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGkgPSBwcFtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChwaS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwY29tczFbaV09XCJBXCI7IC8vIGlmIGNyZWF0ZWQgbXVsdGlwbGUgQzpzLCB0aGVpciBvcmlnaW5hbCBzZWcgaXMgc2F2ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwMiAmJiAocGNvbXMyW2ldPVwiQVwiKTsgLy8gdGhlIHNhbWUgYXMgYWJvdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcC5zcGxpY2UoaSsrLCAwLCBbXCJDXCJdW2NvbmNhdF0ocGkuc3BsaWNlKDAsIDYpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwcC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpaSA9IG1tYXgocC5sZW5ndGgsIHAyICYmIHAyLmxlbmd0aCB8fCAwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZml4TSA9IGZ1bmN0aW9uIChwYXRoMSwgcGF0aDIsIGExLCBhMiwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocGF0aDEgJiYgcGF0aDIgJiYgcGF0aDFbaV1bMF0gPT0gXCJNXCIgJiYgcGF0aDJbaV1bMF0gIT0gXCJNXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGgyLnNwbGljZShpLCAwLCBbXCJNXCIsIGEyLngsIGEyLnldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLmJ4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLmJ5ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLnggPSBwYXRoMVtpXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGExLnkgPSBwYXRoMVtpXVsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlpID0gbW1heChwLmxlbmd0aCwgcDIgJiYgcDIubGVuZ3RoIHx8IDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwY29tczEgPSBbXSwgLy8gcGF0aCBjb21tYW5kcyBvZiBvcmlnaW5hbCBwYXRoIHBcbiAgICAgICAgICAgICAgICBwY29tczIgPSBbXSwgLy8gcGF0aCBjb21tYW5kcyBvZiBvcmlnaW5hbCBwYXRoIHAyXG4gICAgICAgICAgICAgICAgcGZpcnN0ID0gXCJcIiwgLy8gdGVtcG9yYXJ5IGhvbGRlciBmb3Igb3JpZ2luYWwgcGF0aCBjb21tYW5kXG4gICAgICAgICAgICAgICAgcGNvbSA9IFwiXCI7IC8vIGhvbGRlciBmb3IgcHJldmlvdXMgcGF0aCBjb21tYW5kIG9mIG9yaWdpbmFsIHBhdGhcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG1tYXgocC5sZW5ndGgsIHAyICYmIHAyLmxlbmd0aCB8fCAwKTsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwW2ldICYmIChwZmlyc3QgPSBwW2ldWzBdKTsgLy8gc2F2ZSBjdXJyZW50IHBhdGggY29tbWFuZFxuXG4gICAgICAgICAgICAgICAgaWYgKHBmaXJzdCAhPSBcIkNcIikgLy8gQyBpcyBub3Qgc2F2ZWQgeWV0LCBiZWNhdXNlIGl0IG1heSBiZSByZXN1bHQgb2YgY29udmVyc2lvblxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcGNvbXMxW2ldID0gcGZpcnN0OyAvLyBTYXZlIGN1cnJlbnQgcGF0aCBjb21tYW5kXG4gICAgICAgICAgICAgICAgICAgIGkgJiYgKCBwY29tID0gcGNvbXMxW2ktMV0pOyAvLyBHZXQgcHJldmlvdXMgcGF0aCBjb21tYW5kIHBjb21cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcFtpXSA9IHByb2Nlc3NQYXRoKHBbaV0sIGF0dHJzLCBwY29tKTsgLy8gUHJldmlvdXMgcGF0aCBjb21tYW5kIGlzIGlucHV0dGVkIHRvIHByb2Nlc3NQYXRoXG5cbiAgICAgICAgICAgICAgICBpZiAocGNvbXMxW2ldICE9IFwiQVwiICYmIHBmaXJzdCA9PSBcIkNcIikgcGNvbXMxW2ldID0gXCJDXCI7IC8vIEEgaXMgdGhlIG9ubHkgY29tbWFuZFxuICAgICAgICAgICAgICAgIC8vIHdoaWNoIG1heSBwcm9kdWNlIG11bHRpcGxlIEM6c1xuICAgICAgICAgICAgICAgIC8vIHNvIHdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgQyBpcyBhbHNvIEMgaW4gb3JpZ2luYWwgcGF0aFxuXG4gICAgICAgICAgICAgICAgZml4QXJjKHAsIGkpOyAvLyBmaXhBcmMgYWRkcyBhbHNvIHRoZSByaWdodCBhbW91bnQgb2YgQTpzIHRvIHBjb21zMVxuXG4gICAgICAgICAgICAgICAgaWYgKHAyKSB7IC8vIHRoZSBzYW1lIHByb2NlZHVyZXMgaXMgZG9uZSB0byBwMlxuICAgICAgICAgICAgICAgICAgICBwMltpXSAmJiAocGZpcnN0ID0gcDJbaV1bMF0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGZpcnN0ICE9IFwiQ1wiKVxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwY29tczJbaV0gPSBwZmlyc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICBpICYmIChwY29tID0gcGNvbXMyW2ktMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHAyW2ldID0gcHJvY2Vzc1BhdGgocDJbaV0sIGF0dHJzMiwgcGNvbSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBjb21zMltpXSE9XCJBXCIgJiYgcGZpcnN0PT1cIkNcIikgcGNvbXMyW2ldPVwiQ1wiO1xuXG4gICAgICAgICAgICAgICAgICAgIGZpeEFyYyhwMiwgaSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpeE0ocCwgcDIsIGF0dHJzLCBhdHRyczIsIGkpO1xuICAgICAgICAgICAgICAgIGZpeE0ocDIsIHAsIGF0dHJzMiwgYXR0cnMsIGkpO1xuICAgICAgICAgICAgICAgI
57590HZhciBzZWcgPSBwW2ldLFxuICAgICAgICAgICAgICAgICAgICBzZWcyID0gcDIgJiYgcDJbaV0sXG4gICAgICAgICAgICAgICAgICAgIHNlZ2xlbiA9IHNlZy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIHNlZzJsZW4gPSBwMiAmJiBzZWcyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBhdHRycy54ID0gc2VnW3NlZ2xlbiAtIDJdO1xuICAgICAgICAgICAgICAgIGF0dHJzLnkgPSBzZWdbc2VnbGVuIC0gMV07XG4gICAgICAgICAgICAgICAgYXR0cnMuYnggPSB0b0Zsb2F0KHNlZ1tzZWdsZW4gLSA0XSkgfHwgYXR0cnMueDtcbiAgICAgICAgICAgICAgICBhdHRycy5ieSA9IHRvRmxvYXQoc2VnW3NlZ2xlbiAtIDNdKSB8fCBhdHRycy55O1xuICAgICAgICAgICAgICAgIGF0dHJzMi5ieCA9IHAyICYmICh0b0Zsb2F0KHNlZzJbc2VnMmxlbiAtIDRdKSB8fCBhdHRyczIueCk7XG4gICAgICAgICAgICAgICAgYXR0cnMyLmJ5ID0gcDIgJiYgKHRvRmxvYXQoc2VnMltzZWcybGVuIC0gM10pIHx8IGF0dHJzMi55KTtcbiAgICAgICAgICAgICAgICBhdHRyczIueCA9IHAyICYmIHNlZzJbc2VnMmxlbiAtIDJdO1xuICAgICAgICAgICAgICAgIGF0dHJzMi55ID0gcDIgJiYgc2VnMltzZWcybGVuIC0gMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXAyKSB7XG4gICAgICAgICAgICAgICAgcHRoLmN1cnZlID0gcGF0aENsb25lKHApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHAyID8gW3AsIHAyXSA6IHA7XG4gICAgICAgIH0sIG51bGwsIHBhdGhDbG9uZSksXG4gICAgICAgIHBhcnNlRG90cyA9IFIuX3BhcnNlRG90cyA9IGNhY2hlcihmdW5jdGlvbiAoZ3JhZGllbnQpIHtcbiAgICAgICAgICAgIHZhciBkb3RzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBncmFkaWVudC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvdCA9IHt9LFxuICAgICAgICAgICAgICAgICAgICBwYXIgPSBncmFkaWVudFtpXS5tYXRjaCgvXihbXjpdKik6PyhbXFxkXFwuXSopLyk7XG4gICAgICAgICAgICAgICAgZG90LmNvbG9yID0gUi5nZXRSR0IocGFyWzFdKTtcbiAgICAgICAgICAgICAgICBpZiAoZG90LmNvbG9yLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkb3Qub3BhY2l0eSA9IGRvdC5jb2xvci5vcGFjaXR5O1xuICAgICAgICAgICAgICAgIGRvdC5jb2xvciA9IGRvdC5jb2xvci5oZXg7XG4gICAgICAgICAgICAgICAgcGFyWzJdICYmIChkb3Qub2Zmc2V0ID0gcGFyWzJdICsgXCIlXCIpO1xuICAgICAgICAgICAgICAgIGRvdHMucHVzaChkb3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChpID0gMSwgaWkgPSBkb3RzLmxlbmd0aCAtIDE7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb3RzW2ldLm9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgc3RhcnQgPSB0b0Zsb2F0KGRvdHNbaSAtIDFdLm9mZnNldCB8fCAwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8IGlpOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb3RzW2pdLm9mZnNldCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IGRvdHNbal0ub2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSAxMDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBqID0gaWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZW5kID0gdG9GbG9hdChlbmQpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZCA9IChlbmQgLSBzdGFydCkgLyAoaiAtIGkgKyAxKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICg7IGkgPCBqOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ICs9IGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb3RzW2ldLm9mZnNldCA9IHN0YXJ0ICsgXCIlXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZG90cztcbiAgICAgICAgfSksXG4gICAgICAgIHRlYXIgPSBSLl90ZWFyID0gZnVuY3Rpb24gKGVsLCBwYXBlcikge1xuICAgICAgICAgICAgZWwgPT0gcGFwZXIudG9wICYmIChwYXBlci
5759050b3AgPSBlbC5wcmV2KTtcbiAgICAgICAgICAgIGVsID09IHBhcGVyLmJvdHRvbSAmJiAocGFwZXIuYm90dG9tID0gZWwubmV4dCk7XG4gICAgICAgICAgICBlbC5uZXh0ICYmIChlbC5uZXh0LnByZXYgPSBlbC5wcmV2KTtcbiAgICAgICAgICAgIGVsLnByZXYgJiYgKGVsLnByZXYubmV4dCA9IGVsLm5leHQpO1xuICAgICAgICB9LFxuICAgICAgICB0b2Zyb250ID0gUi5fdG9mcm9udCA9IGZ1bmN0aW9uIChlbCwgcGFwZXIpIHtcbiAgICAgICAgICAgIGlmIChwYXBlci50b3AgPT09IGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGVhcihlbCwgcGFwZXIpO1xuICAgICAgICAgICAgZWwubmV4dCA9IG51bGw7XG4gICAgICAgICAgICBlbC5wcmV2ID0gcGFwZXIudG9wO1xuICAgICAgICAgICAgcGFwZXIudG9wLm5leHQgPSBlbDtcbiAgICAgICAgICAgIHBhcGVyLnRvcCA9IGVsO1xuICAgICAgICB9LFxuICAgICAgICB0b2JhY2sgPSBSLl90b2JhY2sgPSBmdW5jdGlvbiAoZWwsIHBhcGVyKSB7XG4gICAgICAgICAgICBpZiAocGFwZXIuYm90dG9tID09PSBlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRlYXIoZWwsIHBhcGVyKTtcbiAgICAgICAgICAgIGVsLm5leHQgPSBwYXBlci5ib3R0b207XG4gICAgICAgICAgICBlbC5wcmV2ID0gbnVsbDtcbiAgICAgICAgICAgIHBhcGVyLmJvdHRvbS5wcmV2ID0gZWw7XG4gICAgICAgICAgICBwYXBlci5ib3R0b20gPSBlbDtcbiAgICAgICAgfSxcbiAgICAgICAgaW5zZXJ0YWZ0ZXIgPSBSLl9pbnNlcnRhZnRlciA9IGZ1bmN0aW9uIChlbCwgZWwyLCBwYXBlcikge1xuICAgICAgICAgICAgdGVhcihlbCwgcGFwZXIpO1xuICAgICAgICAgICAgZWwyID09IHBhcGVyLnRvcCAmJiAocGFwZXIudG9wID0gZWwpO1xuICAgICAgICAgICAgZWwyLm5leHQgJiYgKGVsMi5uZXh0LnByZXYgPSBlbCk7XG4gICAgICAgICAgICBlbC5uZXh0ID0gZWwyLm5leHQ7XG4gICAgICAgICAgICBlbC5wcmV2ID0gZWwyO1xuICAgICAgICAgICAgZWwyLm5leHQgPSBlbDtcbiAgICAgICAgfSxcbiAgICAgICAgaW5zZXJ0YmVmb3JlID0gUi5faW5zZXJ0YmVmb3JlID0gZnVuY3Rpb24gKGVsLCBlbDIsIHBhcGVyKSB7XG4gICAgICAgICAgICB0ZWFyKGVsLCBwYXBlcik7XG4gICAgICAgICAgICBlbDIgPT0gcGFwZXIuYm90dG9tICYmIChwYXBlci
575905ib3R0b20gPSBlbCk7XG4gICAgICAgICAgICBlbDIucHJldiAmJiAoZWwyLnByZXYubmV4dCA9IGVsKTtcbiAgICAgICAgICAgIGVsLnByZXYgPSBlbDIucHJldjtcbiAgICAgICAgICAgIGVsMi5wcmV2ID0gZWw7XG4gICAgICAgICAgICBlbC5uZXh0ID0gZWwyO1xuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwudG9NYXRyaXhcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFV0aWxpdHkgbWV0aG9kXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZXR1cm5zIG1hdHJpeCBvZiB0cmFuc2Zvcm1hdGlvbnMgYXBwbGllZCB0byBhIGdpdmVuIHBhdGhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBwYXRoIChzdHJpbmcpIHBhdGggc3RyaW5nXG4gICAgICAgICAtIHRyYW5zZm9ybSAoc3RyaW5nfGFycmF5KSB0cmFuc2Zvcm1hdGlvbiBzdHJpbmdcbiAgICAgICAgID0gKG9iamVjdCkgQE1hdHJpeFxuICAgICAgICBcXCovXG4gICAgICAgIHRvTWF0cml4ID0gUi50b01hdHJpeCA9IGZ1bmN0aW9uIChwYXRoLCB0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIHZhciBiYiA9IHBhdGhEaW1lbnNpb25zKHBhdGgpLFxuICAgICAgICAgICAgICAgIGVsID0ge1xuICAgICAgICAgICAgICAgICAgICBfOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IEVcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0QkJveDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0oZWwsIHRyYW5zZm9ybSk7XG4gICAgICAgICAgICByZXR1cm4gZWwubWF0cml4O1xuICAgICAgICB9LFxuICAgICAgICAvKlxcXG4gICAgICAgICAqIFJhcGhhZWwudHJhbnNmb3JtUGF0aFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybnMgcGF0aCB0cmFuc2Zvcm1lZCBieSBhIGdpdmVuIHRyYW5zZm9ybWF0aW9uXG4gICAgICAgICA+IFBhcmFtZXRlcnNcbiAgICAgICAgIC0gcGF0aCAoc3RyaW5nKSBwYXRoIHN0cmluZ1xuICAgICAgICAgLSB0cmFuc2Zvcm0gKHN0cmluZ3xhcnJheSkgdHJhbnNmb3JtYXRpb24gc3RyaW5nXG4gICAgICAgICA9IChzdHJpbmcpIHBhdGhcbiAgICAgICAgXFwqL1xuICAgICAgICB0cmFuc2Zvcm1QYXRoID0gUi50cmFuc2Zvcm1QYXRoID0gZnVuY3Rpb24gKHBhdGgsIHRyYW5zZm9ybSkge1xuICAgICAgICAgICAgcmV0dXJuIG1hcFBhdGgocGF0aCwgdG9NYXRyaXgocGF0aCwgdHJhbnNmb3JtKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0gPSBSLl9leHRyYWN0VHJhbnNmb3JtID0gZnVuY3Rpb24gKGVsLCB0c3RyKSB7XG4gICAgICAgICAgICBpZiAodHN0ciA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsLl8udHJhbnNmb3JtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHN0ciA9IFN0cih0c3RyKS5yZXBsYWNlKC9cXC57M318XFx1MjAyNi9nLCBlbC5fLnRyYW5zZm9ybSB8fCBFKTtcbiAgICAgICAgICAgIHZhciB0ZGF0YSA9IFIucGFyc2VUcmFuc2Zvcm1TdHJpbmcodHN0ciksXG4gICAgICAgICAgICAgICAgZGVnID0gMCxcbiAgICAgICAgICAgICAgICBkeCA9IDAsXG4gICAgICAgICAgICAgICAgZHkgPSAwLFxuICAgICAgICAgICAgICAgIHN4ID0gMSxcbiAgICAgICAgICAgICAgICBzeSA9IDEsXG4gICAgICAgICAgICAgICAgXyA9IGVsLl8sXG4gICAgICAgICAgICAgICAgbSA9IG5ldyBNYXRyaXg7XG4gICAgICAgICAgICBfLnRyYW5zZm9ybSA9IHRkYXRhIHx8IFtdO1xuICAgICAgICAgICAgaWYgKHRkYXRhKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgdCA9IHRkYXRhW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGxlbiA9IHQubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29tbWFuZCA9IFN0cih0WzBdKS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWJzb2x1dGUgPSB0WzBdICE9IGNvbW1hbmQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnZlciA9IGFic29sdXRlID8gbS5pbnZlcnQoKSA6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICB4MSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHkxLFxuICAgICAgICAgICAgICAgICAgICAgICAgeDIsXG4gICAgICAgICAgICAgICAgICAgICAgICB5MixcbiAgICAgICAgICAgICAgICAgICAgICAgIGJiO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29tbWFuZCA9PSBcInRcIiAmJiB0bGVuID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgxID0gaW52ZXIueCgwLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5MSA9IGludmVyLnkoMCwgMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeDIgPSBpbnZlci54KHRbMV0sIHRbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzFdLCB0WzJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnRyYW5zbGF0ZSh4MiAtIHgxLCB5MiAtIHkxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbS50cmFuc2xhdGUodFsxXSwgdFsyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZCA9PSBcInJcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRsZW4gPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJiID0gYmIgfHwgZWwuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnJvdGF0ZSh0WzFdLCBiYi54ICsgYmIud2lkdGggLyAyLCBiYi55ICsgYmIuaGVpZ2h0IC8gMik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVnICs9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRsZW4gPT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IGludmVyLngodFsyXSwgdFszXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzJdLCB0WzNdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5yb3RhdGUodFsxXSwgeDIsIHkyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLnJvdGF0ZSh0WzFdLCB0WzJdLCB0WzNdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVnICs9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29tbWFuZCA9PSBcInNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRsZW4gPT0gMiB8fCB0bGVuID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYiA9IGJiIHx8IGVsLmdldEJCb3goMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5zY2FsZSh0WzFdLCB0W3RsZW4gLSAxXSwgYmIueCArIGJiLndpZHRoIC8gMiwgYmIueSArIGJiLmhlaWdodCAvIDIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN4ICo9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3kgKj0gdFt0bGVuIC0gMV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRsZW4gPT0gNSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4MiA9IGludmVyLngodFszXSwgdFs0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkyID0gaW52ZXIueSh0WzNdLCB0WzRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5zY2FsZSh0WzFdLCB0WzJdLCB4MiwgeTIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG0uc2NhbGUodFsxXSwgdFsyXSwgdFszXSwgdFs0XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN4ICo9IHRbMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3kgKj0gdFsyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjb21tYW5kID09IFwibVwiICYmIHRsZW4gPT0gNykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbS5hZGQodFsxXSwgdFsyXSwgdFszXSwgdFs0XSwgdFs1XSwgdFs2XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgXy5kaXJ0eVQgPSAxO1xuICAgICAgICAgICAgICAgICAgICBlbC5tYXRyaXggPSBtO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLypcXFxuICAgICAgICAgICAgICogRWxlbWVudC5tYXRyaXhcbiAgICAgICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICAgICAqKlxuICAgICAgICAgICAgICogS2VlcHMgQE1hdHJpeCBvYmplY3QsIHdoaWNoIHJlcHJlc2VudHMgZWxlbWVudCB0cmFuc2Zvcm1hdGlvblxuICAgICAgICAgICAgXFwqL1xuICAgICAgICAgICAgZWwubWF0cml4ID0gbTtcblxuICAgICAgICAgICAgXy5zeCA9IHN4O1xuICAgICAgICAgICAgXy5zeSA9IHN5O1xuICAgICAgICAgICAgXy5kZWcgPSBkZWc7XG4gICAgICAgICAgICBfLmR4ID0gZHggPSBtLmU7XG4gICAgICAgICAgICBfLmR5ID0gZHkgPSBtLmY7XG5cbiAgICAgICAgICAgIGlmIChzeCA9PSAxICYmIHN5ID09IDEgJiYgIWRlZyAmJiBfLmJib3gpIHtcbiAgICAgICAgICAgICAgICBfLmJib3gueCArPSArZHg7XG4gICAgICAgICAgICAgICAgXy5iYm94
57590LnkgKz0gK2R5O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBfLmRpcnR5VCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGdldEVtcHR5ID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgIHZhciBsID0gaXRlbVswXTtcbiAgICAgICAgICAgIHN3aXRjaCAobC50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcInRcIjogcmV0dXJuIFtsLCAwLCAwXTtcbiAgICAgICAgICAgICAgICBjYXNlIFwibVwiOiByZXR1cm4gW2wsIDEsIDAsIDAsIDEsIDAsIDBdO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJyXCI6IGlmIChpdGVtLmxlbmd0aCA9PSA0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbbCwgMCwgaXRlbVsyXSwgaXRlbVszXV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAwXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSBcInNcIjogaWYgKGl0ZW0ubGVuZ3RoID09IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAxLCAxLCBpdGVtWzNdLCBpdGVtWzRdXTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGl0ZW0ubGVuZ3RoID09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtsLCAxLCAxXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2wsIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXF1YWxpc2VUcmFuc2Zvcm0gPSBSLl9lcXVhbGlzZVRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0MSwgdDIpIHtcbiAgICAgICAgICAgIHQyID0gU3RyKHQyKS5yZXBsYWNlKC9cXC57M318XFx1MjAyNi9nLCB0MSk7XG4gICAgICAgICAgICB0MSA9IFIucGFyc2VUcmFuc2Zvcm1TdHJpbmcodDEpIHx8IFtdO1xuICAgICAgICAgICAgdDIgPSBSLnBhcnNlVHJhbnNmb3JtU3RyaW5nKHQyKSB8fCBbXTtcbiAgICAgICAgICAgIHZhciBtYXhsZW5ndGggPSBtbWF4KHQxLmxlbmd0aCwgdDIubGVuZ3RoKSxcbiAgICAgICAgICAgICAgICBmcm9tID0gW10sXG4gICAgICAgICAgICAgICAgdG8gPSBbXSxcbiAgICAgICAgICAgICAgICBpID0gMCwgaiwgamosXG4gICAgICAgICAgICAgICAgdHQxLCB0dDI7XG4gICAgICAgICAgICBmb3IgKDsgaSA8IG1heGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdHQxID0gdDFbaV0gfHwgZ2V0RW1wdHkodDJbaV0pO1xuICAgICAgICAgICAgICAgIHR0MiA9IHQyW2ldIHx8IGdldEVtcHR5KHR0MSk7XG4gICAgICAgICAgICAgICAgaWYgKCh0dDFbMF0gIT0gdHQyWzBdKSB8fFxuICAgICAgICAgICAgICAgICAgICAodHQxWzBdLnRvTG93ZXJDYXNlKCkgPT0gXCJyXCIgJiYgKHR0MVsyXSAhPSB0dDJbMl0gfHwgdHQxWzNdICE9IHR0MlszXSkpIHx8XG4gICAgICAgICAgICAgICAgICAgICh0dDFbMF0udG9Mb3dlckNhc2UoKSA9PSBcInNcIiAmJiAodHQxWzNdICE9IHR0MlszXSB8fCB0dDFbNF0gIT0gdHQyWzRdKSlcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnJvbVtpXSA9IFtdO1xuICAgICAgICAgICAgICAgIHRvW2ldID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMCwgamogPSBtbWF4KHR0MS5sZW5ndGgsIHR0Mi5sZW5ndGgpOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBqIGluIHR0MSAmJiAoZnJvbVtpXVtqXSA9IHR0MVtqXSk7XG4gICAgICAgICAgICAgICAgICAgIGogaW4gdHQyICYmICh0b1tpXVtqXSA9IHR0MltqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmcm9tOiBmcm9tLFxuICAgICAgICAgICAgICAgIHRvOiB0b1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICBSLl9nZXRDb250YWluZXIgPSBmdW5jdGlvbiAoeCwgeSwgdywgaCkge1xuICAgICAgICB2Y
57590XIgY29udGFpbmVyO1xuICAgICAgICBjb250YWluZXIgPSBoID09IG51bGwgJiYgIVIuaXMoeCwgXCJvYmplY3RcIikgPyBnLmRvYy5nZXRFbGVtZW50QnlJZCh4KSA6IHg7XG4gICAgICAgIGlmIChjb250YWluZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb250YWluZXIudGFnTmFtZSkge1xuICAgICAgICAgICAgaWYgKHkgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogY29udGFpbmVyLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogY29udGFpbmVyLnN0eWxlLnBpeGVsV2lkdGggfHwgY29udGFpbmVyLm9mZnNldFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5zdHlsZS5waXhlbEhlaWdodCB8fCBjb250YWluZXIub2Zmc2V0SGVpZ2h0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiB5LFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHdcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb250YWluZXI6IDEsXG4gICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgIHdpZHRoOiB3LFxuICAgICAgICAgICAgaGVpZ2h0OiBoXG4gICAgICAgIH07XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5wYXRoVG9SZWxhdGl2ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBDb252ZXJ0cyBwYXRoIHRvIHJlbGF0aXZlIGZvcm1cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gcGF0aFN0cmluZyAoc3RyaW5nfGFycmF5KSBwYXRoIHN0cmluZyBvciBhcnJheSBvZiBzZWdtZW50c1xuICAgICA9IChhcnJheSkgYXJyYXkgb2Ygc2VnbWVudHMuXG4gICAgXFwqL1xuICAgIFIucGF0aFRvUmVsYXRpdmUgPSBwYXRoVG9SZWxhdGl2ZTtcbiAgICBSLl9lbmdpbmUgPSB7fTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5wYXRoMmN1cnZlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBVdGlsaXR5IG1ldGhvZFxuICAgICAqKlxuICAgICAqIENvbnZlcnRzIHBhdGggdG8gYSBuZXcgcGF0aCB3aGVyZSBhbGwgc2VnbWVudHMgYXJlIGN1YmljIGJlemllciBjdXJ2ZXMuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGhTdHJpbmcgKHN0cmluZ3xhcnJheSkgcGF0aCBzdHJpbmcgb3IgYXJyYXkgb2Ygc2VnbWVudHNcbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIHNlZ21lbnRzLlxuICAgIFxcKi9cbiAgICBSLnBhdGgyY3VydmUgPSBwYXRoMmN1cnZlO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLm1hdHJpeFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogVXRpbGl0eSBtZXRob2RcbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIG1hdHJpeCBiYXNlZCBvbiBnaXZlbiBwYXJhbWV0ZXJzLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBhIChudW1iZXIpXG4gICAgIC0gYiAobnVtYmVyKVxuICAgICAtIGMgKG51bWJlcilcbiAgICAgLSBkIChudW1iZXIpXG4gICAgIC0gZSAobnVtYmVyKVxuICAgICAtIGYgKG51bWJlcilcbiAgICAgPSAob2JqZWN0KSBATWF0cml4XG4gICAgXFwqL1xuICAgIFIubWF0cml4ID0gZnVuY3Rpb24gKGEsIGIsIGMsIGQsIGUsIGYpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNYXRyaXgoYSwgYiwgYywgZCwgZSwgZik7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBNYXRyaXgoYSwgYiwgYywgZCwgZSwgZikge1xuICAgICAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmEgPSArYTtcbiAgICAgICAgICAgIHRoaXMuYiA9ICtiO1xuICAgICAgICAgICAgdGhpcy5jID0gK2M7XG4gICAgICAgICAgICB0aGlzLmQgPSArZDtcbiAgICAgICAgICAgIHRoaXMuZSA9ICtlO1xuICAgICAgICAgICAgdGhpcy5mID0gK2Y7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmEgPSAxO1xuICAgICAgICAgICAgdGhpcy5iID0gMDtcbiAgICAgICAgICAgIHRoaXMuYyA9IDA7XG4gICAgICAgICAgICB0aGlzLmQgPSAxO1xuICAgICAgICAgICAgdGhpcy5lID0gMDtcbiAgICAgICAgICAgIHRoaXMuZiA9IDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgKGZ1bmN0aW9uIChtYXRyaXhwcm90bykge1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5hZGRcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIEFkZHMgZ2l2ZW4gbWF0cml4IHRvIGV4aXN0aW5nIG9uZS5cbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBhIChudW1iZXIpXG4gICAgICAgICAtIGIgKG51bWJlcilcbiAgICAgICAgIC0gYyAobnVtYmVyKVxuICAgICAgICAgLSBkIChudW1iZXIpXG4gICAgICAgICAtIGUgKG51bWJlcilcbiAgICAgICAgIC0gZiAobnVtYmVyKVxuICAgICAgICAgb3JcbiAgICAgICAgIC0gbWF0cml4IChvYmplY3QpIEBNYXRyaXhcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5hZGQgPSBmdW5jdGlvbiAoYSwgYiwgYywgZCwgZSwgZikge1xuICAgICAgICAgICAgdmFyIG91dCA9IFtbXSwgW10sIFtdXSxcbiAgICAgICAgICAgICAgICBtID0gW1t0aGlzLmEsIHRoaXMuYywgdGhpcy5lXSwgW3RoaXMuYiwgdGhpcy5kLCB0aGlzLmZdLCBbMCwgMCwgMV1dLFxuICAgICAgICAgICAgICAgIG1hdHJpeCA9IFtbYSwgYywgZV0sIFtiLCBkLCBmXSwgWzAsIDAsIDFdXSxcbiAgICAgICAgICAgICAgICB4LCB5LCB6LCByZXM7XG5cbiAgICAgICAgICAgIGlmIChhICYmIGEgaW5zdGFuY2VvZiBNYXRyaXgpIHtcbiAgICAgICAgICAgICAgICBtYXRyaXggPSBbW2EuYSwgYS5jLCBhLmVdLCBbYS5iLCBhLmQsIGEuZl0sIFswLCAwLCAxXV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHggPCAzOyB4KyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKHkgPSAwOyB5IDwgMzsgeSsrKSB7XG4gICAgICAgICAgICAgICAgICAgI
57590HJlcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoeiA9IDA7IHogPCAzOyB6KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcyArPSBtW3hdW3pdICogbWF0cml4W3pdW3ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG91dFt4XVt5XSA9IHJlcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmEgPSBvdXRbMF1bMF07XG4gICAgICAgICAgICB0aGlzLmIgPSBvdXRbMV1bMF07XG4gICAgICAgICAgICB0aGlzLmMgPSBvdXRbMF1bMV07XG4gICAgICAgICAgICB0aGlzLmQgPSBvdXRbMV1bMV07XG4gICAgICAgICAgICB0aGlzLmUgPSBvdXRbMF1bMl07XG4gICAgICAgICAgICB0aGlzLmYgPSBvdXRbMV1bMl07XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LmludmVydFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmV0dXJucyBpbnZlcnRlZCB2ZXJzaW9uIG9mIHRoZSBtYXRyaXhcbiAgICAgICAgID0gKG9iamVjdCkgQE1hdHJpeFxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLmludmVydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBtZSA9IHRoaXMsXG4gICAgICAgICAgICAgICAgeCA9IG1lLmEgKiBtZS5kIC0gbWUuYiAqIG1lLmM7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1hdHJpeChtZS5kIC8geCwgLW1lLmIgLyB4LCAtbWUuYyAvIHgsIG1lLmEgLyB4LCAobWUuYyAqIG1lLmYgLSBtZS5kICogbWUuZSkgLyB4LCAobWUuYiAqIG1lLmUgLSBtZS5hICogbWUuZikgLyB4KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXguY2xvbmVcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybnMgY29weSBvZiB0aGUgbWF0cml4XG4gICAgICAgICA9IChvYmplY3QpIEBNYXRyaXhcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTWF0cml4KHRoaXMuYSwgdGhpcy5iLCB0aGlzLmMsIHRoaXMuZCwgdGhpcy5lLCB0aGlzLmYpO1xuICAgICAgICB9O1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC50cmFuc2xhdGVcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFRyYW5zbGF0ZSB0aGUgbWF0cml4XG4gICAgICAgICA+IFBhcmFtZXRlcnNcbiAgICAgICAgIC0geCAobnVtYmVyKVxuICAgICAgICAgLSB5IChudW1iZXIpXG4gICAgICAgIFxcKi9cbiAgICAgICAgbWF0cml4cHJvdG8udHJhbnNsYXRlID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkKDEsIDAsIDAsIDEsIHgsIHkpO1xuICAgICAgICB9O1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5zY2FsZVxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogU2NhbGVzIHRoZSBtYXRyaXhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSB4IChudW1iZXIpXG4gICAgICAgICAtIHkgKG51bWJlcikgI29wdGlvbmFsXG4gICAgICAgICAtIGN4IChudW1iZXIpICNvcHRpb25hbFxuICAgICAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWxcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5zY2FsZSA9IGZ1bmN0aW9uICh4LCB5LCBjeCwgY3kpIHtcbiAgICAgICAgICAgIHkgPT0gbnVsbCAmJiAoeSA9IHgpO1xuICAgICAgICAgICAgKGN4IHx8IGN5KSAmJiB0aGlzLmFkZCgxLCAwLCAwLCAxLCBjeCwgY3kpO1xuICAgICAgICAgICAgdGhpcy5hZGQoeCwgMCwgMCwgeSwgMCwgMCk7XG4gICAgICAgICAgICAoY3ggfHwgY3kpICYmIHRoaXMuYWRkKDEsIDAsIDAsIDEsIC1jeCwgLWN5KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXgucm90YXRlXG4gICAgICAgICBbIG1ldGhvZCBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSb3RhdGVzIHRoZSBtYXRyaXhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSBhIChudW1iZXIpXG4gICAgICAgICAtIHggKG51bWJlcilcbiAgICAgICAgIC0geSAobnVtYmVyKVxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLnJvdGF0ZSA9IGZ1bmN0aW9uIChhLCB4LCB5KSB7XG4gICAgICAgICAgICBhID0gUi5yYWQoYSk7XG4gICAgICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICAgICAgeSA9IHkgfHwgMDtcbiAgICAgICAgICAgIHZhciBjb3MgPSArbWF0aC5jb3MoYSkudG9GaXhlZCg5KSxcbiAgICAgICAgICAgICAgICBzaW4gPSArbWF0aC5zaW4oYSkudG9GaXhlZCg5KTtcbiAgICAgICAgICAgIHRoaXMuYWRkKGNvcywgc2luLCAtc2luLCBjb3MsIHgsIHkpO1xuICAgICAgICAgICAgdGhpcy5hZGQoMSwgMCwgMCwgMSwgLXgsIC15KTtcbiAgICAgICAgfTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBNYXRyaXgueFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmV0dXJuIHggY29vcmRpbmF0ZSBmb3IgZ2l2ZW4gcG9pbnQgYWZ0ZXIgdHJhbnNmb3JtYXRpb24gZGVzY3JpYmVkIGJ5IHRoZSBtYXRyaXguIFNlZSBhbHNvIEBNYXRyaXgueVxuICAgICAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICAgICAtIHggKG51bWJlcilcbiAgICAgICAgIC0geSAobnVtYmVyKVxuICAgICAgICAgPSAobnVtYmVyKSB4XG4gICAgICAgIFxcKi9cbiAgICAgICAgbWF0cml4cHJvdG8ueCA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgICAgICByZXR1cm4geCAqIHRoaXMuYSArIHkgKiB0aGlzLmMgKyB0aGlzLmU7XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LnlcbiAgICAgICAgIFsgbWV0aG9kIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIFJldHVybiB5IGNvb3JkaW5hdGUgZm9yIGdpdmVuIHBvaW50IGFmdGVyIHRyYW5zZm9ybWF0aW9uIGRlc2NyaWJlZCBieSB0aGUgbWF0cml4LiBTZWUgYWxzbyBATWF0cml4LnhcbiAgICAgICAgID4gUGFyYW1ldGVyc1xuICAgICAgICAgLSB4IChudW1iZXIpXG4gICAgICAgICAtIHkgKG51bWJlcilcbiAgICAgICAgID0gKG51bWJlcikgeVxuICAgICAgICBcXCovXG4gICAgICAgIG1hdHJpeHByb3RvLnkgPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgICAgICAgICAgcmV0dXJuIHggKiB0aGlzLmIgKyB5ICogdGhpcy5kICsgdGh
57590pcy5mO1xuICAgICAgICB9O1xuICAgICAgICBtYXRyaXhwcm90by5nZXQgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgcmV0dXJuICt0aGlzW1N0ci5mcm9tQ2hhckNvZGUoOTcgKyBpKV0udG9GaXhlZCg0KTtcbiAgICAgICAgfTtcbiAgICAgICAgbWF0cml4cHJvdG8udG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUi5zdmcgP1xuICAgICAgICAgICAgICAgIFwibWF0cml4KFwiICsgW3RoaXMuZ2V0KDApLCB0aGlzLmdldCgxKSwgdGhpcy5nZXQoMiksIHRoaXMuZ2V0KDMpLCB0aGlzLmdldCg0KSwgdGhpcy5nZXQoNSldLmpvaW4oKSArIFwiKVwiIDpcbiAgICAgICAgICAgICAgICBbdGhpcy5nZXQoMCksIHRoaXMuZ2V0KDIpLCB0aGlzLmdldCgxKSwgdGhpcy5nZXQoMyksIDAsIDBdLmpvaW4oKTtcbiAgICAgICAgfTtcbiAgICAgICAgbWF0cml4cHJvdG8udG9GaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJwcm9naWQ6RFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuTWF0cml4KE0xMT1cIiArIHRoaXMuZ2V0KDApICtcbiAgICAgICAgICAgICAgICBcIiwgTTEyPVwiICsgdGhpcy5nZXQoMikgKyBcIiwgTTIxPVwiICsgdGhpcy5nZXQoMSkgKyBcIiwgTTIyPVwiICsgdGhpcy5nZXQoMykgK1xuICAgICAgICAgICAgICAgIFwiLCBEeD1cIiArIHRoaXMuZ2V0KDQpICsgXCIsIER5PVwiICsgdGhpcy5nZXQoNSkgKyBcIiwgc2l6aW5nbWV0aG9kPSdhdXRvIGV4cGFuZCcpXCI7XG4gICAgICAgIH07XG4gICAgICAgIG1hdHJpeHByb3RvLm9mZnNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBbdGhpcy5lLnRvRml4ZWQoNCksIHRoaXMuZi50b0ZpeGVkKDQpXTtcbiAgICAgICAgfTtcbiAgICAgICAgZnVuY3Rpb24gbm9ybShhKSB7XG4gICAgICAgICAgICByZXR1cm4gYVswXSAqIGFbMF0gKyBhWzFdICogYVsxXTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBub3JtYWxpemUoYSkge1xuICAgICAgICAgICAgdmFyIG1hZyA9IG1hdGguc3FydChub3JtKGEpKTtcbiAgICAgICAgICAgIGFbMF0gJiYgKGFbMF0gLz0gbWFnKTtcbiAgICAgICAgICAgIGFbMV0gJiYgKGFbMV0gLz0gbWFnKTtcbiAgICAgICAgfVxuICAgICAgICAvKlxcXG4gICAgICAgICAqIE1hdHJpeC5zcGxpdFxuICAgICAgICAgWyBtZXRob2QgXVxuICAgICAgICAgKipcbiAgICAgICAgICogU3BsaXRzIG1hdHJpeCBpbnRvIHByaW1pdGl2ZSB0cmFuc2Zvcm1hdGlvbnNcbiAgICAgICAgID0gKG9iamVjdCkgaW4gZm9ybWF0OlxuICAgICAgICAgbyBkeCAobnVtYmVyKSB0cmFuc2xhdGlvbiBieSB4XG4gICAgICAgICBvIGR5IChudW1iZXIpIHRyYW5zbGF0aW9uIGJ5IHlcbiAgICAgICAgIG8gc2NhbGV4IChudW1iZXIpIHNjYWxlIGJ5IHhcbiAgICAgICAgIG8gc2NhbGV5IChudW1iZXIpIHNjYWxlIGJ5IHlcbiAgICAgICAgIG8gc2hlYXIgKG51bWJlcikgc2hlYXJcbiAgICAgICAgIG8gcm90YXRlIChudW1iZXIpIHJvdGF0aW9uIGluIGRlZ1xuICAgICAgICAgbyBpc1NpbXBsZSAoYm9vbGVhbikgY291bGQgaXQgYmUgcmVwcmVzZW50ZWQgdmlhIHNpbXBsZSB0cmFuc2Zvcm1hdGlvbnNcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by5z
57590cGxpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBvdXQgPSB7fTtcbiAgICAgICAgICAgIC8vIHRyYW5zbGF0aW9uXG4gICAgICAgICAgICBvdXQuZHggPSB0aGlzLmU7XG4gICAgICAgICAgICBvdXQuZHkgPSB0aGlzLmY7XG5cbiAgICAgICAgICAgIC8vIHNjYWxlIGFuZCBzaGVhclxuICAgICAgICAgICAgdmFyIHJvdyA9IFtbdGhpcy5hLCB0aGlzLmNdLCBbdGhpcy5iLCB0aGlzLmRdXTtcbiAgICAgICAgICAgIG91dC5zY2FsZXggPSBtYXRoLnNxcnQobm9ybShyb3dbMF0pKTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZShyb3dbMF0pO1xuXG4gICAgICAgICAgICBvdXQuc2hlYXIgPSByb3dbMF1bMF0gKiByb3dbMV1bMF0gKyByb3dbMF1bMV0gKiByb3dbMV1bMV07XG4gICAgICAgICAgICByb3dbMV0gPSBbcm93WzFdWzBdIC0gcm93WzBdWzBdICogb3V0LnNoZWFyLCByb3dbMV1bMV0gLSByb3dbMF1bMV0gKiBvdXQuc2hlYXJdO1xuXG4gICAgICAgICAgICBvdXQuc2NhbGV5ID0gbWF0aC5zcXJ0KG5vcm0ocm93WzFdKSk7XG4gICAgICAgICAgICBub3JtYWxpemUocm93WzFdKTtcbiAgICAgICAgICAgIG91dC5zaGVhciAvPSBvdXQuc2NhbGV5O1xuXG4gICAgICAgICAgICAvLyByb3RhdGlvblxuICAgICAgICAgICAgdmFyIHNpbiA9IC1yb3dbMF1bMV0sXG4gICAgICAgICAgICAgICAgY29zID0gcm93WzFdWzFdO1xuICAgICAgICAgICAgaWYgKGNvcyA8IDApIHtcbiAgICAgICAgICAgICAgICBvdXQucm90YXRlID0gUi5kZWcobWF0aC5hY29zKGNvcykpO1xuICAgICAgICAgICAgICAgIGlmIChzaW4gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC5yb3RhdGUgPSAzNjAgLSBvdXQucm90YXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3V0LnJvdGF0ZSA9IFIuZGVnKG1hdGguYXNpbihzaW4pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3V0LmlzU2ltcGxlID0gIStvdXQuc2hlYXIudG9GaXhlZCg5KSAmJiAob3V0LnNjYWxleC50b0ZpeGVkKDkpID09IG91dC5zY2FsZXkudG9GaXhlZCg5KSB8fCAhb3V0LnJvdGF0ZSk7XG4gICAgICAgICAgICBvdXQuaXNTdXBlclNpbXBsZSA9ICErb3V0LnNoZWFyLnRvRml4ZWQoOSkgJiYgb3V0LnNjYWxleC50b0ZpeGVkKDkpID09IG91dC5zY2FsZXkudG9GaXhlZCg5KSAmJiAhb3V0LnJvdGF0ZTtcbiAgICAgICAgICAgIG91dC5ub1JvdGF0aW9uID0gIStvdXQuc2hlYXIudG9GaXhlZCg5KSAmJiAhb3V0LnJvdGF0ZTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogTWF0cml4LnRvVHJhbnNmb3JtU3RyaW5nXG4gICAgICAgICBbIG1ldGhvZCBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZXR1cm4gdHJhbnNmb3JtIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgZ2l2ZW4gbWF0cml4XG4gICAgICAgICA9IChzdHJpbmcpIHRyYW5zZm9ybSBzdHJpbmdcbiAgICAgICAgXFwqL1xuICAgICAgICBtYXRyaXhwcm90by50b1RyYW5zZm9ybVN0cmluZyA9IGZ1bmN0aW9uIChzaG9ydGVyKSB7XG4gICAgICAgICAgICB2Y
57590XIgcyA9IHNob3J0ZXIgfHwgdGhpc1tzcGxpdF0oKTtcbiAgICAgICAgICAgIGlmIChzLmlzU2ltcGxlKSB7XG4gICAgICAgICAgICAgICAgcy5zY2FsZXggPSArcy5zY2FsZXgudG9GaXhlZCg0KTtcbiAgICAgICAgICAgICAgICBzLnNjYWxleSA9ICtzLnNjYWxleS50b0ZpeGVkKDQpO1xuICAgICAgICAgICAgICAgIHMucm90YXRlID0gK3Mucm90YXRlLnRvRml4ZWQoNCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICAocy5keCB8fCBzLmR5ID8gXCJ0XCIgKyBbcy5keCwgcy5keV0gOiBFKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAocy5zY2FsZXggIT0gMSB8fCBzLnNjYWxleSAhPSAxID8gXCJzXCIgKyBbcy5zY2FsZXgsIHMuc2NhbGV5LCAwLCAwXSA6IEUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgIChzLnJvdGF0ZSA/IFwiclwiICsgW3Mucm90YXRlLCAwLCAwXSA6IEUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJtXCIgKyBbdGhpcy5nZXQoMCksIHRoaXMuZ2V0KDEpLCB0aGlzLmdldCgyKSwgdGhpcy5nZXQoMyksIHRoaXMuZ2V0KDQpLCB0aGlzLmdldCg1KV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfSkoTWF0cml4LnByb3RvdHlwZSk7XG5cbiAgICB2YXIgcHJldmVudERlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICB9LFxuICAgIHByZXZlbnRUb3VjaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3JpZ2luYWxFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sXG4gICAgc3RvcFByb3BhZ2F0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNhbmNlbEJ1YmJsZSA9IHRydWU7XG4gICAgfSxcbiAgICBzdG9wVG91Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfSxcbiAgICBnZXRFdmVudFBvc2l0aW9uID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHNjcm9sbFkgPSBnLmRvYy5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGcuZG9jLmJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogZS5jbGllbnRYICsgc2Nyb2xsWCxcbiAgICAgICAgICAgIHk6IGUuY2xpZW50WSArIHNjcm9sbFlcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGFkZEV2ZW50ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGcuZG9jLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqLCB0eXBlLCBmbiwgZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHZhciBmID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGdldEV2ZW50UG9zaXRpb24oZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmbi5jYWxsKGVsZW1lbnQsIGUsIHBvcy54LCBwb3MueSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvYmouYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoc3VwcG9ydHNUb3VjaCAmJiB0b3VjaE1hcFt0eXBlXSkge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgX2YgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGdldEV2ZW50UG9zaXRpb24oZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkZSA9IGU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGUudGFyZ2V0VG91Y2hlcyAmJiBlLnRhcmdldFRvdWNoZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlLnRhcmdldFRvdWNoZXNbaV0udGFyZ2V0ID09IG9iaikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlID0gZS50YXJnZXRUb3VjaGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLm9yaWdpbmFsRXZlbnQgPSBvbGRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0ID0gcHJldmVudFRvdWNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbiA9IHN0b3BUb3VjaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm4uY2FsbChlbGVtZW50LCBlLCBwb3MueCwgcG9zLnkpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBvYmouYWRkRXZlbnRMaXN0ZW5lcih0b3VjaE1hcFt0eXBlXSwgX2YsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBmLCBmYWxzZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHN1cHBvcnRzVG91Y2ggJiYgdG91Y2hNYXBbdHlwZV0pXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcih0b3VjaE1hcFt0eXBlXSwgX2YsIGZhbHNlKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChnLmRvYy5hdHRhY2hFdmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChvYmosIHR5cGUsIGZuLCBlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIGYgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBlID0gZSB8fCBnLndpbi5ldmVudDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNjcm9sbFkgPSBnLmRvYy5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8IGcuZG9jLmJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBlLmNsaWVudFggKyBzY3JvbGxYLFxuICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGUuY2xpZW50WSArIHNjcm9sbFk7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQgPSBlLnByZXZlbnREZWZhdWx0IHx8IHByZXZlbnREZWZhdWx0O1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbiA9IGUuc3RvcFByb3BhZ2F0aW9uIHx8IHN0b3BQcm9wYWdhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuLmNhbGwoZWxlbWVudCwgZSwgeCwgeSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBvYmouYXR0YWNoRXZlbnQoXCJvblwiICsgdHlwZSwgZik7XG4gICAgICAgICAgICAgICAgdmFyIGRldGFjaGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBvYmouZGV0YWNoRXZlbnQoXCJvblwiICsgdHlwZSwgZik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRldGFjaGVyO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0pKCksXG4gICAgZHJhZyA9IFtdLFxuICAgIGRyYWdNb3ZlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHggPSBlLmNsaWVudFgsXG4gICAgICAgICAgICB5ID0gZS5jbGllbnRZLFxuICAgICAgICAgICAgc2Nyb2xsWSA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZy5kb2MuYm9keS5zY3JvbGxUb3AsXG4gICAgICAgICAgICBzY3JvbGxYID0gZy5kb2MuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgfHwgZy5kb2MuYm9keS5zY3JvbGxMZWZ0LFxuICAgICAgICAgICAgZHJhZ2ksXG4gICAgICAgICAgICBqID0gZHJhZy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChqLS0pIHtcbiAgICAgICAgICAgIGRyYWdpID0gZHJhZ1tqXTtcbiAgICAgICAgICAgIGlmIChzdXBwb3J0c1RvdWNoICYmIGUudG91Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpID0gZS50b3VjaGVzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgdG91Y2g7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgICAgICB0b3VjaCA9IGUudG91Y2hlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRvdWNoLmlkZW50aWZpZXIgPT0gZHJhZ2kuZWwuX2RyYWcuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSB0b3VjaC5jbGllbnRYO1xuICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHRvdWNoLmNsaWVudFk7XG4gICAgICAgICAgICAgICAgICAgICAgICAoZS5vcmlnaW5hbEV2ZW50ID8gZS5vcmlnaW5hbEV2ZW50IDogZSkucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2Y
57590XIgbm9kZSA9IGRyYWdpLmVsLm5vZGUsXG4gICAgICAgICAgICAgICAgbyxcbiAgICAgICAgICAgICAgICBuZXh0ID0gbm9kZS5uZXh0U2libGluZyxcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBub2RlLnBhcmVudE5vZGUsXG4gICAgICAgICAgICAgICAgZGlzcGxheSA9IG5vZGUuc3R5bGUuZGlzcGxheTtcbiAgICAgICAgICAgIGcud2luLm9wZXJhICYmIHBhcmVudC5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgIG5vZGUuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgbyA9IGRyYWdpLmVsLnBhcGVyLmdldEVsZW1lbnRCeVBvaW50KHgsIHkpO1xuICAgICAgICAgICAgbm9kZS5zdHlsZS5kaXNwbGF5ID0gZGlzcGxheTtcbiAgICAgICAgICAgIGcud2luLm9wZXJhICYmIChuZXh0ID8gcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCBuZXh0KSA6IHBhcmVudC5hcHBlbmRDaGlsZChub2RlKSk7XG4gICAgICAgICAgICBvICYmIGV2ZShcInJhcGhhZWwuZHJhZy5vdmVyLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLmVsLCBvKTtcbiAgICAgICAgICAgIHggKz0gc2Nyb2xsWDtcbiAgICAgICAgICAgIHkgKz0gc2Nyb2xsWTtcbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuZHJhZy5tb3ZlLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLm1vdmVfc2NvcGUgfHwgZHJhZ2kuZWwsIHggLSBkcmFnaS5lbC5fZHJhZy54LCB5IC0gZHJhZ2kuZWwuX2RyYWcueSwgeCwgeSwgZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRyYWdVcCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIFIudW5tb3VzZW1vdmUoZHJhZ01vdmUpLnVubW91c2V1cChkcmFnVXApO1xuICAgICAgICB2Y
57590XIgaSA9IGRyYWcubGVuZ3RoLFxuICAgICAgICAgICAgZHJhZ2k7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGRyYWdpID0gZHJhZ1tpXTtcbiAgICAgICAgICAgIGRyYWdpLmVsLl9kcmFnID0ge307XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmRyYWcuZW5kLlwiICsgZHJhZ2kuZWwuaWQsIGRyYWdpLmVuZF9zY29wZSB8fCBkcmFnaS5zdGFydF9zY29wZSB8fCBkcmFnaS5tb3ZlX3Njb3BlIHx8IGRyYWdpLmVsLCBlKTtcbiAgICAgICAgfVxuICAgICAgICBkcmFnID0gW107XG4gICAgfSxcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5lbFxuICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgKipcbiAgICAgKiBZb3UgY2FuIGFkZCB5b3VyIG93biBtZXRob2QgdG8gZWxlbWVudHMuIFRoaXMgaXMgdXNlZnVsIHdoZW4geW91IHdhbnQgdG8gaGFjayBkZWZhdWx0IGZ1bmN0aW9uYWxpdHkgb3JcbiAgICAgKiB3YW50IHRvIHdyYXAgc29tZSBjb21tb24gdHJhbnNmb3JtYXRpb24gb3IgYXR0cmlidXRlcyBpbiBvbmUgbWV0aG9kLiBJbiBkaWZmZXJlbmNlIHRvIGNhbnZhcyBtZXRob2RzLFxuICAgICAqIHlvdSBjYW4gcmVkZWZpbmUgZWxlbWVudCBtZXRob2QgYXQgYW55IHRpbWUuIEV4cGVuZGluZyBlbGVtZW50IG1ldGhvZHMgd291bGRu4oCZdCBhZmZlY3Qgc2V0LlxuICAgICA+IFVzYWdlXG4gICAgIHwgUmFwaGFlbC5lbC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgIHwgICAgIHRoaXMuYXR0cih7ZmlsbDogXCIjZjAwXCJ9KTtcbiAgICAgfCB9O1xuICAgICB8IC8vIHRoZW4gdXNlIGl0XG4gICAgI
57590HwgcGFwZXIuY2lyY2xlKDEwMCwgMTAwLCAyMCkucmVkKCk7XG4gICAgXFwqL1xuICAgIGVscHJvdG8gPSBSLmVsID0ge307XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuY2xpY2tcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5jbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBjbGljayBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5kYmxjbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciBkb3VibGUgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5kYmxjbGlja1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBkb3VibGUgY2xpY2sgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2Vkb3duXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlZG93biBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC51bm1vdXNlZG93blxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZWRvd24gZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2Vtb3ZlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlbW92ZSBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC51bm1vdXNlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZW1vdmUgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQubW91c2VvdXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgbW91c2VvdXQgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5tb3VzZW91dFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciBtb3VzZW91dCBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5tb3VzZW92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgbW91c2VvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVubW91c2VvdmVyXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNlb3ZlciBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG5cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5tb3VzZXVwXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNldXAgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5tb3VzZXVwXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGV2ZW50IGhhbmRsZXIgZm9yIG1vdXNldXAgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudG91Y2hzdGFydFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaHN0YXJ0IGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVudG91Y2hzdGFydFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaHN0YXJ0IGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pICNvcHRpb25hbCBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvdWNobW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaG1vdmUgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW50b3VjaG1vdmVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2htb3ZlIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pICNvcHRpb25hbCBoYW5kbGVyIGZvciB0aGUgZXZlbnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvdWNoZW5kXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBBZGRzIGV2ZW50IGhhbmRsZXIgZm9yIHRvdWNoZW5kIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gaGFuZGxlciAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVudG91Y2hlbmRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2hlbmQgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgI29wdGlvbmFsIGhhbmRsZXIgZm9yIHRoZSBldmVudFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudG91Y2hjYW5jZWxcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlciBmb3IgdG91Y2hjYW5jZWwgZm9yIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBoYW5kbGVyIChmdW5jdGlvbikgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW50b3VjaGNhbmNlbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBldmVudCBoYW5kbGVyIGZvciB0b3VjaGNhbmNlbCBmb3IgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGhhbmRsZXIgKGZ1bmN0aW9uKSAjb3B0aW9uYWwgaGFuZGxlciBmb3IgdGhlIGV2ZW50XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgZm9yICh2YXIgaSA9IGV2ZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgKGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgICAgIFJbZXZlbnROYW1lXSA9IGVscHJvdG9bZXZlbnROYW1lXSA9IGZ1bmN0aW9uIChmbiwgc2NvcGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoUi5pcyhmbiwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50cyA9IHRoaXMuZXZlbnRzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50cy5wdXNoKHtuYW1lOiBldmVudE5hbWUsIGY6IGZuLCB1bmJpbmQ6IGFkZEV2ZW50KHRoaXMuc2hhcGUgfHwgdGhpcy5ub2RlIHx8IGcuZG9jLCBldmVudE5hbWUsIGZuLCBzY29wZSB8fCB0aGlzKX0pO1xuICAgICAgICAgICAgICAgI
57590H1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBSW1widW5cIiArIGV2ZW50TmFtZV0gPSBlbHByb3RvW1widW5cIiArIGV2ZW50TmFtZV0gPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5ldmVudHMgfHwgW10sXG4gICAgICAgICAgICAgICAgICAgIGwgPSBldmVudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHdoaWxlIChsLS0pe1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnRzW2xdLm5hbWUgPT0gZXZlbnROYW1lICYmIChSLmlzKGZuLCBcInVuZGVmaW5lZFwiKSB8fCBldmVudHNbbF0uZiA9PSBmbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1tsXS51bmJpbmQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cy5zcGxpY2UobCwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAhZXZlbnRzLmxlbmd0aCAmJiBkZWxldGUgdGhpcy5ldmVudHM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KShldmVudHNbaV0pO1xuICAgIH1cblxuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmRhdGFcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgb3IgcmV0cmlldmVzIGdpdmVuIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCBnaXZlbiBrZXkuXG4gICAgICoqXG4gICAgICogU2VlIGFsc28gQEVsZW1lbnQucmVtb3ZlRGF0YVxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBrZXkgKHN0cmluZykga2V5IHRvIHN0b3JlIGRhdGFcbiAgICAgLSB2YWx1ZSAoYW55KSAjb3B0aW9uYWwgdmFsdWUgdG8gc3RvcmVcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgICAqIG9yLCBpZiB2YWx1ZSBpcyBub3Qgc3BlY2lmaWVkOlxuICAgICA9IChhbnkpIHZhbHVlXG4gICAgICogb3IsIGlmIGtleSBhbmQgdmFsdWUgYXJlIG5vdCBzcGVjaWZpZWQ6XG4gICAgID0gKG9iamVjdCkgS2V5L3ZhbHVlIHBhaXJzIGZvciBhbGwgdGhlIGRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBlbGVtZW50LlxuICAgICA+IFVzYWdlXG4gICAgIHwgZm9yICh2YXIgaSA9IDAsIGkgPCA1LCBpKyspIHtcbiAgICAgfCAgICAgcGFwZXIuY2lyY2xlKDEwICsgMTUgKiBpLCAxMCwgMTApXG4gICAgIHwgICAgICAgICAgLmF0dHIoe2ZpbGw6IFwiIzAwMFwifSlcbiAgICAgfCAgICAgICAgICAuZGF0YShcImlcIiwgaSlcbiAgICAgfCAgICAgICAgICAuY2xpY2soZnVuY3Rpb24gKCkge1xuICAgICB8ICAgICAgICAgICAgIGFsZXJ0KHRoaXMuZGF0YShcImlcIikpO1xuICAgICB8ICAgICAgICAgIH0pO1xuICAgICB8IH1cbiAgICBcXCovXG4gICAgZWxwcm90by5kYXRhID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBlbGRhdGFbdGhpcy5pZF0gPSBlbGRhdGFbdGhpcy5pZF0gfHwge307XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgIGlmIChSLmlzKGtleSwgXCJvYmplY3RcIikpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIGtleSkgaWYgKGtleVtoYXNdKGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YShpLCBrZXlbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuZGF0YS5nZXQuXCIgKyB0aGlzLmlkLCB0aGlzLCBkYXRhW2tleV0sIGtleSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YVtrZXldO1xuICAgICAgICB9XG4gICAgICAgIGRhdGFba2V5XSA9IHZhbHVlO1xuICAgICAgICBldmUoXCJyYXBoYWVsLmRhdGEuc2V0LlwiICsgdGhpcy5pZCwgdGhpcywgdmFsdWUsIGtleSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucmVtb3ZlRGF0YVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggYW4gZWxlbWVudCBieSBnaXZlbiBrZXkuXG4gICAgICogSWYga2V5IGlzIG5vdCBwcm92aWRlZCwgcmVtb3ZlcyBhbGwgdGhlIGRhdGEgb2YgdGhlIGVsZW1lbnQuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIGtleSAoc3RyaW5nKSAjb3B0aW9uYWwga2V5XG4gICAgID0gKG9iamVjdCkgQEVsZW1lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5yZW1vdmVEYXRhID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBlbGRhdGFbdGhpcy5pZF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGRhdGFbdGhpcy5pZF0gJiYgZGVsZXRlIGVsZGF0YVt0aGlzLmlkXVtrZXldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmdldERhdGFcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHJpZXZlcyB0aGUgZWxlbWVudCBkYXRhXG4gICAgID0gKG9iamVjdCkgZGF0YVxuICAgIFxcKi9cbiAgICBlbHByb3RvLmdldERhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBjbG9uZShlbGRhdGFbdGhpcy5pZF0gfHwge30pO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaG92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZXZlbnQgaGFuZGxlcnMgZm9yIGhvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZl9pbiAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGhvdmVyIGluXG4gICAgIC0gZl9vdXQgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciBob3ZlciBvdXRcbiAgICAgLSBpY29udGV4dCAob2JqZWN0KSAjb3B0aW9uYWwgY29udGV4dCBmb3IgaG92ZXIgaW4gaGFuZGxlclxuICAgICAtIG9jb250ZXh0IChvYmplY3QpICNvcHRpb25hbCBjb250ZXh0IGZvciBob3ZlciBvdXQgaGFuZGxlclxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaG92ZXIgPSBmdW5jdGlvbiAoZl9pbiwgZl9vdXQsIHNjb3BlX2luLCBzY29wZV9vdXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW91c2VvdmVyKGZfaW4sIHNjb3BlX2luKS5tb3VzZW91dChmX291dCwgc2NvcGVfb3V0IHx8IHNjb3BlX2luKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnVuaG92ZXJcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZXZlbnQgaGFuZGxlcnMgZm9yIGhvdmVyIGZvciB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZl9pbiAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGhvdmVyIGluXG4gICAgIC0gZl9vdXQgKGZ1bmN0aW9uKSBoYW5kbGVyIGZvciBob3ZlciBvdXRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnVuaG92ZXIgPSBmdW5jdGlvbiAoZl9pbiwgZl9vdXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudW5tb3VzZW92ZXIoZl9pbikudW5tb3VzZW91dChmX291dCk7XG4gICAgfTtcbiAgICB2YXIgZ
57590HJhZ2dhYmxlID0gW107XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZHJhZ1xuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBldmVudCBoYW5kbGVycyBmb3IgZHJhZyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gb25tb3ZlIChmdW5jdGlvbikgaGFuZGxlciBmb3IgbW92aW5nXG4gICAgIC0gb25zdGFydCAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGRyYWcgc3RhcnRcbiAgICAgLSBvbmVuZCAoZnVuY3Rpb24pIGhhbmRsZXIgZm9yIGRyYWcgZW5kXG4gICAgIC0gbWNvbnRleHQgKG9iamVjdCkgI29wdGlvbmFsIGNvbnRleHQgZm9yIG1vdmluZyBoYW5kbGVyXG4gICAgIC0gc2NvbnRleHQgKG9iamVjdCkgI29wdGlvbmFsIGNvbnRleHQgZm9yIGRyYWcgc3RhcnQgaGFuZGxlclxuICAgICAtIGVjb250ZXh0IChvYmplY3QpICNvcHRpb25hbCBjb250ZXh0IGZvciBkcmFnIGVuZCBoYW5kbGVyXG4gICAgICogQWRkaXRpb25hbGx5IGZvbGxvd2luZyBgZHJhZ2AgZXZlbnRzIHdpbGwgYmUgdHJpZ2dlcmVkOiBgZHJhZy5zdGFydC48aWQ+YCBvbiBzdGFydCxcbiAgICAgKiBgZHJhZy5lbmQuPGlkPmAgb24gZW5kIGFuZCBgZHJhZy5tb3ZlLjxpZD5gIG9uIGV2ZXJ5IG1vdmUuIFdoZW4gZWxlbWVudCB3aWxsIGJlIGRyYWdnZWQgb3ZlciBhbm90aGVyIGVsZW1lbnRcbiAgICAgKiBgZHJhZy5vdmVyLjxpZD5gIHdpbGwgYmUgZmlyZWQgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIFN0YXJ0IGV2ZW50IGFuZCBzdGFydCBoYW5kbGVyIHdpbGwgYmUgY2FsbGVkIGluIHNwZWNpZmllZCBjb250ZXh0IG9yIGluIGNvbnRleHQgb2YgdGhlIGVsZW1lbnQgd2l0aCBmb2xsb3dpbmcgcGFyYW1ldGVyczpcbiAgICAgbyB4IChudW1iZXIpIHggcG9zaXRpb24gb2YgdGhlIG1vdXNlXG4gICAgIG8geSAobnVtYmVyKSB5IHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuICAgICBvIGV2ZW50IChvYmplY3QpIERPTSBldmVudCBvYmplY3RcbiAgICAgKiBNb3ZlIGV2ZW50IGFuZCBtb3ZlIGhhbmRsZXIgd2lsbCBiZSBjYWxsZWQgaW4gc3BlY2lmaWVkIGNvbnRleHQgb3IgaW4gY29udGV4dCBvZiB0aGUgZWxlbWVudCB3aXRoIGZvbGxvd2luZyBwYXJhbWV0ZXJzOlxuICAgICBvIGR4IChudW1iZXIpIHNoaWZ0IGJ5IHggZnJvbSB0aGUgc3RhcnQgcG9pbnRcbiAgICAgbyBkeSAobnVtYmVyKSBzaGlmdCBieSB5IGZyb20gdGhlIHN0YXJ0IHBvaW50XG4gICAgIG8geCAobnVtYmVyKSB4IHBvc2l0aW9uIG9mIHRoZSBtb3VzZVxuICAgICBvIHkgKG51bWJlcikgeSBwb3NpdGlvbiBvZiB0aGUgbW91c2VcbiAgICAgbyBldmVudCAob2JqZWN0KSBET00gZXZlbnQgb2JqZWN0XG4gICAgICogRW5kIGV2ZW50IGFuZCBlbmQgaGFuZGxlciB3aWxsIGJlIGNhbGxlZCBpbiBzcGVjaWZpZWQgY29udGV4dCBvciBpbiBjb250ZXh0IG9mIHRoZSBlbGVtZW50IHdpdGggZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gICAgIG8gZXZlbnQgKG9iamVjdCkgRE9NIGV2ZW50IG9iamVjdFxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uZHJhZyA9IGZ1bmN0aW9uIChvbm1vdmUsIG9uc3RhcnQsIG9uZW5kLCBtb3ZlX3Njb3BlLCBzdGFydF9zY29wZSwgZW5kX3Njb3BlKSB7XG4gICAgICAgIGZ1bmN0aW9uIHN0YXJ0KGUpIHtcbiAgICAgICAgICAgIChlLm9yaWdpbmFsRXZlbnQgfHwgZSkucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHZhciB4ID0gZS5jbGllbnRYLFxuICAgICAgICAgICAgICAgIHkgPSBlLmNsaWVudFksXG4gICAgICAgICAgICAgICAgc2Nyb2xsWSA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZy5kb2MuYm9keS5zY3JvbGxUb3AsXG4gICAgICAgICAgICAgICAgc2Nyb2xsWCA9IGcuZG9jLmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGcuZG9jLmJvZHkuc2Nyb2xsTGVmdDtcbiAgICAgICAgICAgIHRoaXMuX2RyYWcuaWQgPSBlLmlkZW50aWZpZXI7XG4gICAgICAgICAgICBpZiAoc3VwcG9ydHNUb3VjaCAmJiBlLnRvdWNoZXMpIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgaSA9IGUudG91Y2hlcy5sZW5ndGgsIHRvdWNoO1xuICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgdG91Y2ggPSBlLnRvdWNoZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RyYWcuaWQgPSB0b3VjaC5pZGVudGlmaWVyO1xuICAgICAgICAgICAgICAgICAgICBpZiAodG91Y2guaWRlbnRpZmllciA9PSB0aGlzLl9kcmFnLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4ID0gdG91Y2guY2xpZW50WDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB0b3VjaC5jbGllbnRZO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9kcmFnLnggPSB4ICsgc2Nyb2xsWDtcbiAgICAgICAgICAgIHRoaXMuX2RyYWcueSA9IHkgKyBzY3JvbGxZO1xuICAgICAgICAgICAgIWRyYWcubGVuZ3RoICYmIFIubW91c2Vtb3ZlKGRyYWdNb3ZlKS5tb3VzZXVwKGRyYWdVcCk7XG4gICAgICAgICAgICBkcmFnLnB1c2goe2VsOiB0aGlzLCBtb3ZlX3Njb3BlOiBtb3ZlX3Njb3BlLCBzdGFydF9zY29wZTogc3RhcnRfc2NvcGUsIGVuZF9zY29wZTogZW5kX3Njb3BlfSk7XG4gICAgICAgICAgICBvbnN0YXJ0ICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5zdGFydC5cIiArIHRoaXMuaWQsIG9uc3RhcnQpO1xuICAgICAgICAgICAgb25tb3ZlICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5tb3ZlLlwiICsgdGhpcy5pZCwgb25tb3ZlKTtcbiAgICAgICAgICAgIG9uZW5kICYmIGV2ZS5vbihcInJhcGhhZWwuZHJhZy5lbmQuXCIgKyB0aGlzLmlkLCBvbmVuZCk7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmRyYWcuc3RhcnQuXCIgKyB0aGlzLmlkLCBzdGFydF9zY29wZSB8fCBtb3ZlX3Njb3BlIHx8IHRoaXMsIHR
57590oaXMuX2RyYWcueCwgdGhpcy5fZHJhZy55LCBlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9kcmFnID0ge307XG4gICAgICAgIGRyYWdnYWJsZS5wdXNoKHtlbDogdGhpcywgc3RhcnQ6IHN0YXJ0fSk7XG4gICAgICAgIHRoaXMubW91c2Vkb3duKHN0YXJ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5vbkRyYWdPdmVyXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBTaG9ydGN1dCBmb3IgYXNzaWduaW5nIGV2ZW50IGhhbmRsZXIgZm9yIGBkcmFnLm92ZXIuPGlkPmAgZXZlbnQsIHdoZXJlIGlkIGlzIGlkIG9mIHRoZSBlbGVtZW50IChzZWUgQEVsZW1lbnQuaWQpLlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBmIChmdW5jdGlvbikgaGFuZGxlciBmb3IgZXZlbnQsIGZpcnN0IGFyZ3VtZW50IHdvdWxkIGJlIHRoZSBlbGVtZW50IHlvdSBhcmUgZHJhZ2dpbmcgb3ZlclxuICAgIFxcKi9cbiAgICBlbHByb3RvLm9uRHJhZ092ZXIgPSBmdW5jdGlvbiAoZikge1xuICAgICAgICBmID8gZXZlLm9uKFwicmFwaGFlbC5kcmFnLm92ZXIuXCIgKyB0aGlzLmlkLCBmKSA6IGV2ZS51bmJpbmQoXCJyYXBoYWVsLmRyYWcub3Zlci5cIiArIHRoaXMuaWQpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudW5kcmFnXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGFsbCBkcmFnIGV2ZW50IGhhbmRsZXJzIGZyb20gZ2l2ZW4gZWxlbWVudC5cbiAgICBcXCovXG4gICAgZWxwcm90by51bmRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpID0gZHJhZ2dhYmxlLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSkgaWYgKGRyYWdnYWJsZVtpXS5lbCA9PSB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzLnVubW91c2Vkb3duKGRyYWdnYWJsZVtpXS5zdGFydCk7XG4gICAgICAgICAgICBkcmFnZ2FibGUuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgZXZlLnVuYmluZChcInJhcGhhZWwuZHJhZy4qLlwiICsgdGhpcy5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgIWRyYWdnYWJsZS5sZW5ndGggJiYgUi51bm1vdXNlbW92ZShkcmFnTW92ZSkudW5tb3VzZXVwKGRyYWdVcCk7XG4gICAgICAgIGRyYWcgPSBbXTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5jaXJjbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERyYXdzIGEgY2lyY2xlLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgY2VudHJlXG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIGNlbnRyZVxuICAgICAtIHIgKG51bWJlcikgcmFkaXVzXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3Qgd2l0aCB0eXBlIOKAnGNpcmNsZeKAnVxuICAgICAqKlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5jaXJjbGUoNTAsIDUwLCA0MCk7XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uY2lyY2xlID0gZnVuY3Rpb24gKHgsIHksIHIpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS5jaXJjbGUodGhpcywgeCB8fCAwLCB5IHx8IDAsIHIgfHwgMCk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlY3RcbiAgICAgWyBtZXRob2QgXVxuICAgICAqXG4gICAgICogRHJhd3MgYSByZWN0YW5nbGUuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHggKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSB0b3AgbGVmdCBjb3JuZXJcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wIGxlZnQgY29ybmVyXG4gICAgIC0gd2lkdGggKG51bWJlcikgd2lkdGhcbiAgICAgLSBoZWlnaHQgKG51bWJlcikgaGVpZ2h0XG4gICAgIC0gciAobnVtYmVyKSAjb3B0aW9uYWwgcmFkaXVzIGZvciByb3VuZGVkIGNvcm5lcnMsIGRlZmF1bHQgaXMgMFxuICAgICA9IChvYmplY3QpIFJhcGhhw6tsIGVsZW1lbnQgb2JqZWN0IHdpdGggdHlwZSDigJxyZWN04oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCAvLyByZWd1bGFyIHJlY3RhbmdsZVxuICAgICB8IHZhciBjID0gcGFwZXIucmVjdCgxMCwgMTAsIDUwLCA1MCk7XG4gICAgI
57590HwgLy8gcmVjdGFuZ2xlIHdpdGggcm91bmRlZCBjb3JuZXJzXG4gICAgIHwgdmFyIGMgPSBwYXBlci5yZWN0KDQwLCA0MCwgNTAsIDUwLCAxMCk7XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucmVjdCA9IGZ1bmN0aW9uICh4LCB5LCB3LCBoLCByKSB7XG4gICAgICAgIHZhciBvdXQgPSBSLl9lbmdpbmUucmVjdCh0aGlzLCB4IHx8IDAsIHkgfHwgMCwgdyB8fCAwLCBoIHx8IDAsIHIgfHwgMCk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmVsbGlwc2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERyYXdzIGFuIGVsbGlwc2UuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHggKG51bWJlcikgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmVcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgY2VudHJlXG4gICAgIC0gcnggKG51bWJlcikgaG9yaXpvbnRhbCByYWRpdXNcbiAgICAgLSByeSAobnVtYmVyKSB2ZXJ0aWNhbCByYWRpdXNcbiAgICAgPSAob2JqZWN0KSBSYXBoYcOrbCBlbGVtZW50IG9iamVjdCB3aXRoIHR5cGUg4oCcZWxsaXBzZeKAnVxuICAgICAqKlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5lbGxpcHNlKDUwLCA1MCwgNDAsIDIwKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5lbGxpcHNlID0gZnVuY3Rpb24gKHgsIHksIHJ4LCByeSkge1xuICAgICAgICB2Y
57590XIgb3V0ID0gUi5fZW5naW5lLmVsbGlwc2UodGhpcywgeCB8fCAwLCB5IHx8IDAsIHJ4IHx8IDAsIHJ5IHx8IDApO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5wYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGEgcGF0aCBlbGVtZW50IGJ5IGdpdmVuIHBhdGggZGF0YSBzdHJpbmcuXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHBhdGhTdHJpbmcgKHN0cmluZykgI29wdGlvbmFsIHBhdGggc3RyaW5nIGluIFNWRyBmb3JtYXQuXG4gICAgICogUGF0aCBzdHJpbmcgY29uc2lzdHMgb2Ygb25lLWxldHRlciBjb21tYW5kcywgZm9sbG93ZWQgYnkgY29tbWEgc2VwcmFyYXRlZCBhcmd1bWVudHMgaW4gbnVtZXJjYWwgZm9ybS4gRXhhbXBsZTpcbiAgICAgfCBcIk0xMCwyMEwzMCw0MFwiXG4gICAgICogSGVyZSB3ZSBjYW4gc2VlIHR3byBjb21tYW5kczog4oCcTeKAnSwgd2l0aCBhcmd1bWVudHMgYCgxMCwgMjApYCBhbmQg4oCcTOKAnSB3aXRoIGFyZ3VtZW50cyBgKDMwLCA0MClgLiBVcHBlciBjYXNlIGxldHRlciBtZWFuIGNvbW1hbmQgaXMgYWJzb2x1dGUsIGxvd2VyIGNhc2XigJRyZWxhdGl2ZS5cbiAgICAgKlxuICAgICAjIDxwPkhlcmUgaXMgc2hvcnQgbGlzdCBvZiBjb21tYW5kcyBhdmFpbGFibGUsIGZvciBtb3JlIGRldGFpbHMgc2VlIDxhIGhyZWY9XCJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcvcGF0aHMuaHRtbCNQYXRoRGF0YVwiIHRpdGxlPVwiRGV0YWlscyBvZiBhIHBhdGgncyBkYXRhIGF0dHJpYnV0ZSdzIGZvcm1hdCBhcmUgZGVzY3JpYmVkIGluIHRoZSBTVkcgc3BlY2lmaWNhdGlvbi5cIj5TVkcgcGF0aCBzdHJpbmcgZm9ybWF0PC9hPi48L3A+XG4gICAgICMgPHRhYmxlPjx0aGVhZD48dHI+PHRoPkNvbW1hbmQ8L3RoPjx0aD5OYW1lPC90aD48dGg+UGFyYW1ldGVyczwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT5cbiAgICAgIyA8dHI+PHRkPk08L3RkPjx0ZD5tb3ZldG88L3RkPjx0ZD4oeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5aPC90ZD48dGQ+Y2xvc2VwYXRoPC90ZD48dGQ+KG5vbmUpPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+TDwvdGQ+PHRkPmxpbmV0bzwvdGQ+PHRkPih4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPkg8L3RkPjx0ZD5ob3Jpem9udGFsIGxpbmV0bzwvdGQ+PHRkPngrPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+VjwvdGQ+PHRkPnZlcnRpY2FsIGxpbmV0bzwvdGQ+PHRkPnkrPC90ZD48L3RyPlxuICAgICAjIDx0cj48dGQ+QzwvdGQ+PHRkPmN1cnZldG88L3RkPjx0ZD4oeDEgeTEgeDIgeTIgeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5TPC90ZD48dGQ+c21vb3RoIGN1cnZldG88L3RkPjx0ZD4oeDIgeTIgeCB5KSs8L3RkPjwvdHI+XG4gICAgICMgPHRyPjx0ZD5RPC90ZD48dGQ+cXVhZHJhdGljIELDqXppZXIgY3VydmV0bzwvdGQ+PHRkPih4MSB5MSB4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPlQ8L3RkPjx0ZD5zbW9vdGggcXVhZHJhdGljIELDqXppZXIgY3VydmV0bzwvdGQ+PHRkPih4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPkE8L3RkPjx0ZD5lbGxpcHRpY2FsIGFyYzwvdGQ+PHRkPihyeCByeSB4LWF4aXMtcm90YXRpb24gbGFyZ2UtYXJjLWZsYWcgc3dlZXAtZmxhZyB4IHkpKzwvdGQ+PC90cj5cbiAgICAgIyA8dHI+PHRkPlI8L3RkPjx0ZD48YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DYXRtdWxs4oCTUm9tX3NwbGluZSNDYXRtdWxsLkUyLjgwLjkzUm9tX3NwbGluZVwiPkNhdG11bGwtUm9tIGN1cnZldG88L2E+KjwvdGQ+PHRkPngxIHkxICh4IHkpKzwvdGQ+PC90cj48L3Rib2R5PjwvdGFibGU+XG4gICAgICogKiDigJxDYXRtdWxsLVJvbSBjdXJ2ZXRv4oCdIGlzIGEgbm90IHN0YW5kYXJkIFNWRyBjb21tYW5kIGFuZCBhZGRlZCBpbiAyLjAgdG8gbWFrZSBsaWZlIGVhc2llci5cbiAgICAgKiBOb3RlOiB0aGVyZSBpcyBhIHNwZWNpYWwgY2FzZSB3aGVuIHBhdGggY29uc2lzdCBvZiBqdXN0IHRocmVlIGNvbW1hbmRzOiDigJxNMTAsMTBS4oCmeuKAnS4gSW4gdGhpcyBjYXNlIHBhdGggd2lsbCBzbW9vdGhseSBjb25uZWN0cyB0byBpdHMgYmVnaW5uaW5nLlxuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIGMgPSBwYXBlci5wYXRoKFwiTTEwIDEwTDkwIDkwXCIpO1xuICAgICB8IC8vIGRyYXcgYSBkaWFnb25hbCBsaW5lOlxuICAgICB8IC8vIG1vdmUgdG8gMTAsMTAsIGxpbmUgdG8gOTAsOTBcbiAgICAgKiBGb3IgZXhhbXBsZSBvZiBwYXRoIHN0cmluZ3MsIGNoZWNrIG91dCB0aGVzZSBpY29uczogaHR0cDovL3JhcGhhZWxqcy5jb20vaWNvbnMvXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucGF0aCA9IGZ1bmN0aW9uIChwYXRoU3RyaW5nKSB7XG4gICAgICAgIHBhdGhTdHJpbmcgJiYgIVIuaXMocGF0aFN0cmluZywgc3RyaW5nKSAmJiAhUi5pcyhwYXRoU3RyaW5nWzBdLCBhcnJheSkgJiYgKHBhdGhTdHJpbmcgKz0gRSk7XG4gICAgICAgIHZhciBvdXQgPSBSLl9lbmdpbmUucGF0aChSLmZvcm1hdFthcHBseV0oUiwgYXJndW1lbnRzKSwgdGhpcyk7XG4gICAgICAgIHRoaXMuX19zZXRfXyAmJiB0aGlzLl9fc2V0X18ucHVzaChvdXQpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmltYWdlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBFbWJlZHMgYW4gaW1hZ2UgaW50byB0aGUgc3VyZmFjZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gc3JjIChzdHJpbmcpIFVSSSBvZiB0aGUgc291cmNlIGltYWdlXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgcG9zaXRpb25cbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBwb3NpdGlvblxuICAgICAtIHdpZHRoIChudW1iZXIpIHdpZHRoIG9mIHRoZSBpbWFnZVxuICAgICAtIGhlaWdodCAobnVtYmVyKSBoZWlnaHQgb2YgdGhlIGltYWdlXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3Qgd2l0aCB0eXBlIOKAnGltYWdl4oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2
57590VcbiAgICAgfCB2YXIgYyA9IHBhcGVyLmltYWdlKFwiYXBwbGUucG5nXCIsIDEwLCAxMCwgODAsIDgwKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5pbWFnZSA9IGZ1bmN0aW9uIChzcmMsIHgsIHksIHcsIGgpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS5pbWFnZSh0aGlzLCBzcmMgfHwgXCJhYm91dDpibGFua1wiLCB4IHx8IDAsIHkgfHwgMCwgdyB8fCAwLCBoIHx8IDApO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci50ZXh0XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEcmF3cyBhIHRleHQgc3RyaW5nLiBJZiB5b3UgbmVlZCBsaW5lIGJyZWFrcywgcHV0IOKAnFxcbuKAnSBpbiB0aGUgc3RyaW5nLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBwb3NpdGlvblxuICAgICAtIHkgKG51bWJlcikgeSBjb29yZGluYXRlIHBvc2l0aW9uXG4gICAgIC0gdGV4dCAoc3RyaW5nKSBUaGUgdGV4dCBzdHJpbmcgdG8gZHJhd1xuICAgICA9IChvYmplY3QpIFJhcGhhw6tsIGVsZW1lbnQgb2JqZWN0IHdpdGggdHlwZSDigJx0ZXh04oCdXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCB2YXIgdCA9IHBhcGVyLnRleHQoNTAsIDUwLCBcIlJhcGhhw6tsXFxua2lja3NcXG5idXR0IVwiKTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by50ZXh0ID0gZnVuY3Rpb24gKHgsIHksIHRleHQpIHtcbiAgICAgICAgdmFyIG91dCA9IFIuX2VuZ2luZS50ZXh0KHRoaXMsIHggfHwgMCwgeSB8fCAwLCBTdHIodGV4dCkpO1xuICAgICAgICB0aGlzLl9fc2V0X18gJiYgdGhpcy5fX3NldF9fLnB1c2gob3V0KTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYXJyYXktbGlrZSBvYmplY3QgdG8ga2VlcCBhbmQgb3BlcmF0ZSBzZXZlcmFsIGVsZW1lbnRzIGF0IG9uY2UuXG4gICAgICogV2FybmluZzogaXQgZG9lc27igJl0IGNyZWF0ZSBhbnkgZWxlbWVudHMgZm9yIGl0c2VsZiBpbiB0aGUgcGFnZSwgaXQganVzdCBncm91cHMgZXhpc3RpbmcgZWxlbWVudHMuXG4gICAgICogU2V0cyBhY3QgYXMgcHNldWRvIGVsZW1lbnRzIOKAlCBhbGwgbWV0aG9kcyBhdmFpbGFibGUgdG8gYW4gZWxlbWVudCBjYW4gYmUgdXNlZCBvbiBhIHNldC5cbiAgICAgPSAob2JqZWN0KSBhcnJheS1saWtlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgc2V0IG9mIGVsZW1lbnRzXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCB2YXIgc3QgPSBwYXBlci5zZXQoKTtcbiAgICAgfCBzdC5wdXNoKFxuICAgICB8ICAgICBwYXBlci5jaXJjbGUoMTAsIDEwLCA1KSxcbiAgICAgfCAgICAgcGFwZXIuY2lyY2xlKDMwLCAxMCwgNSlcbiAgICAgfCApO1xuICAgICB8IHN0LmF0dHIoe2ZpbGw6IFwicmVkXCJ9KTsgLy8gY2hhbmdlcyB0aGUgZmlsbCBvZiBib3RoIGNpcmNsZXNcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5zZXQgPSBmdW5jdGlvbiAoaXRlbXNBcnJheSkge1xuICAgICAgICAhUi5pcyhpdGVtc0FycmF5LCBcImFycmF5XCIpICYmIChpdGVtc0FycmF5ID0gQXJyYXkucHJvdG90eXBlLnNwbGljZS5jYWxsKGFyZ3VtZW50cywgMCwgYXJndW1lbnRzLmxlbmd0aCkpO1xuICAgICAgICB2Y
57590XIgb3V0ID0gbmV3IFNldChpdGVtc0FycmF5KTtcbiAgICAgICAgdGhpcy5fX3NldF9fICYmIHRoaXMuX19zZXRfXy5wdXNoKG91dCk7XG4gICAgICAgIG91dFtcInBhcGVyXCJdID0gdGhpcztcbiAgICAgICAgb3V0W1widHlwZVwiXSA9IFwic2V0XCI7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuc2V0U3RhcnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgQFBhcGVyLnNldC4gQWxsIGVsZW1lbnRzIHRoYXQgd2lsbCBiZSBjcmVhdGVkIGFmdGVyIGNhbGxpbmcgdGhpcyBtZXRob2QgYW5kIGJlZm9yZSBjYWxsaW5nXG4gICAgICogQFBhcGVyLnNldEZpbmlzaCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBzZXQuXG4gICAgICoqXG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5zZXRTdGFydCgpO1xuICAgICB8IHBhcGVyLmNpcmNsZSgxMCwgMTAsIDUpLFxuICAgICB8IHBhcGVyLmNpcmNsZSgzMCwgMTAsIDUpXG4gICAgIHwgdmFyIHN0ID0gcGFwZXIuc2V0RmluaXNoKCk7XG4gICAgIHwgc3QuYXR0cih7ZmlsbDogXCJyZWRcIn0pOyAvLyBjaGFuZ2VzIHRoZSBmaWxsIG9mIGJvdGggY2lyY2xlc1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLnNldFN0YXJ0ID0gZnVuY3Rpb24gKHNldCkge1xuICAgICAgICB0aGlzLl9fc2V0X18gPSBzZXQgfHwgdGhpcy5zZXQoKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRGaW5pc2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNlZSBAUGFwZXIuc2V0U3RhcnQuIFRoaXMgbWV0aG9kIGZpbmlzaGVzIGNhdGNoaW5nIGFuZCByZXR1cm5zIHJlc3VsdGluZyBzZXQuXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgc2V0XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uc2V0RmluaXNoID0gZnVuY3Rpb24gKHNldCkge1xuICAgICAgICB2Y
57590XIgb3V0ID0gdGhpcy5fX3NldF9fO1xuICAgICAgICBkZWxldGUgdGhpcy5fX3NldF9fO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmdldFNpemVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE9idGFpbnMgY3VycmVudCBwYXBlciBhY3R1YWwgc2l6ZS5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KVxuICAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5jYW52YXMucGFyZW50Tm9kZTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdpZHRoOiBjb250YWluZXIub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGNvbnRhaW5lci5vZmZzZXRIZWlnaHRcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5zZXRTaXplXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJZiB5b3UgbmVlZCB0byBjaGFuZ2UgZGltZW5zaW9ucyBvZiB0aGUgY2FudmFzIGNhbGwgdGhpcyBtZXRob2RcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gd2lkdGggKG51bWJlcikgbmV3IHdpZHRoIG9mIHRoZSBjYW52YXNcbiAgICAgLSBoZWlnaHQgKG51bWJlcikgbmV3IGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uc2V0U2l6ZSA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBSLl9lbmdpbmUuc2V0U2l6ZS5jYWxsKHRoaXMsIHdpZHRoLCBoZWlnaHQpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnNldFZpZXdCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNldHMgdGhlIHZpZXcgYm94IG9mIHRoZSBwYXBlci4gUHJhY3RpY2FsbHkgaXQgZ2l2ZXMgeW91IGFiaWxpdHkgdG8gem9vbSBhbmQgcGFuIHdob2xlIHBhcGVyIHN1cmZhY2UgYnlcbiAgICAgKiBzcGVjaWZ5aW5nIG5ldyBib3VuZGFyaWVzLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIG5ldyB4IHBvc2l0aW9uLCBkZWZhdWx0IGlzIGAwYFxuICAgICAtIHkgKG51bWJlcikgbmV3IHkgcG9zaXRpb24sIGRlZmF1bHQgaXMgYDBgXG4gICAgIC0gdyAobnVtYmVyKSBuZXcgd2lkdGggb2YgdGhlIGNhbnZhc1xuICAgICAtIGggKG51bWJlcikgbmV3IGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgIC0gZml0IChib29sZWFuKSBgdHJ1ZWAgaWYgeW91IHdhbnQgZ3JhcGhpY3MgdG8gZml0IGludG8gbmV3IGJvdW5kYXJ5IGJveFxuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLnNldFZpZXdCb3ggPSBmdW5jdGlvbiAoeCwgeSwgdywgaCwgZml0KSB7XG4gICAgICAgIHJldHVybiBSLl9lbmdpbmUuc2V0Vmlld0JveC5jYWxsKHRoaXMsIHgsIHksIHcsIGgsIGZpdCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIudG9wXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgdG9wbW9zdCBlbGVtZW50IG9uIHRoZSBwYXBlclxuICAgIFxcKi9cbiAgICAvKlxcXG4gICAgICogUGFwZXIuYm90dG9tXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgYm90dG9tIGVsZW1lbnQgb24gdGhlIHBhcGVyXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8udG9wID0gcGFwZXJwcm90by5ib3R0b20gPSBudWxsO1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5yYXBoYWVsXG4gICAgIFsgcHJvcGVydHkgXVxuICAgICAqKlxuICAgICAqIFBvaW50cyB0byB0aGUgQFJhcGhhZWwgb2JqZWN0L2Z1bmN0aW9uXG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8ucmFwaGFlbCA9IFI7XG4gICAgdmFyIGdldE9mZnNldCA9IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIHZhciBib3ggPSBlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFxuICAgICAgICAgICAgZG9jID0gZWxlbS5vd25lckRvY3VtZW50LFxuICAgICAgICAgICAgYm9keSA9IGRvYy5ib2R5LFxuICAgICAgICAgICAgZG9jRWxlbSA9IGRvYy5kb2N1bWVudEVsZW1lbnQsXG4gICAgICAgICAgICBjbGllbnRUb3AgPSBkb2NFbGVtLmNsaWVudFRvcCB8fCBib2R5LmNsaWVudFRvcCB8fCAwLCBjbGllbnRMZWZ0ID0gZG9jRWxlbS5jbGllbnRMZWZ0IHx8IGJvZHkuY2xpZW50TGVmdCB8fCAwLFxuICAgICAgICAgICAgdG9wICA9IGJveC50b3AgICsgKGcud2luLnBhZ2VZT2Zmc2V0IHx8IGRvY0VsZW0uc2Nyb2xsVG9wIHx8IGJvZHkuc2Nyb2xsVG9wICkgLSBjbGllbnRUb3AsXG4gICAgICAgICAgICBsZWZ0ID0gYm94LmxlZnQgKyAoZy53aW4ucGFnZVhPZmZzZXQgfHwgZG9jRWxlbS5zY3JvbGxMZWZ0IHx8IGJvZHkuc2Nyb2xsTGVmdCkgLSBjbGllbnRMZWZ0O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeTogdG9wLFxuICAgICAgICAgICAgeDogbGVmdFxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmdldEVsZW1lbnRCeVBvaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHlvdSB0b3Btb3N0IGVsZW1lbnQgdW5kZXIgZ2l2ZW4gcG9pbnQuXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgUmFwaGHDq2wgZWxlbWVudCBvYmplY3RcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgZnJvbSB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSB3aW5kb3dcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBmcm9tIHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIHdpbmRvd1xuICAgICA+IFVzYWdlXG4gICAgIHwgcGFwZXIuZ2V0RWxlbWVudEJ5UG9pbnQobW91c2VYLCBtb3VzZVkpLmF0dHIoe3N0cm9rZTogXCIjZjAwXCJ9KTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRFbGVtZW50QnlQb2ludCA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBwYXBlciA9IHRoaXMsXG4gICAgICAgICAgICBzdmcgPSBwYXBlci
575905jYW52YXMsXG4gICAgICAgICAgICB0YXJnZXQgPSBnLmRvYy5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgICAgICBpZiAoZy53aW4ub3BlcmEgJiYgdGFyZ2V0LnRhZ05hbWUgPT0gXCJzdmdcIikge1xuICAgICAgICAgICAgdmFyIHNvID0gZ2V0T2Zmc2V0KHN2ZyksXG4gICAgICAgICAgICAgICAgc3IgPSBzdmcuY3JlYXRlU1ZHUmVjdCgpO1xuICAgICAgICAgICAgc3IueCA9IHggLSBzby54O1xuICAgICAgICAgICAgc3IueSA9IHkgLSBzby55O1xuICAgICAgICAgICAgc3Iud2lkdGggPSBzci5oZWlnaHQgPSAxO1xuICAgICAgICAgICAgdmFyIGhpdHMgPSBzdmcuZ2V0SW50ZXJzZWN0aW9uTGlzdChzciwgbnVsbCk7XG4gICAgICAgICAgICBpZiAoaGl0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQgPSBoaXRzW2hpdHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0YXJnZXQucGFyZW50Tm9kZSAmJiB0YXJnZXQgIT0gc3ZnLnBhcmVudE5vZGUgJiYgIXRhcmdldC5yYXBoYWVsKSB7XG4gICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQucGFyZW50Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICB0YXJnZXQgPT0gcGFwZXIuY2FudmFzLnBhcmVudE5vZGUgJiYgKHRhcmdldCA9IHN2Zyk7XG4gICAgICAgIHRhcmdldCA9IHRhcmdldCAmJiB0YXJnZXQucmFwaGFlbCA/IHBhcGVyLmdldEJ5SWQodGFyZ2V0LnJhcGhhZWxpZCkgOiBudWxsO1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0RWxlbWVudHNCeUJCb3hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgc2V0IG9mIGVsZW1lbnRzIHRoYXQgaGF2ZSBhbiBpbnRlcnNlY3RpbmcgYm91bmRpbmcgYm94XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGJib3ggKG9iamVjdCkgYmJveCB0byBjaGVjayB3aXRoXG4gICAgID0gKG9iamVjdCkgQFNldFxuICAgICBcXCovXG4gICAgcGFwZXJwcm90by5nZXRFbGVtZW50c0J5QkJveCA9IGZ1bmN0aW9uIChiYm94KSB7XG4gICAgICAgIHZhciBzZXQgPSB0aGlzLnNldCgpO1xuICAgICAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoUi5pc0JCb3hJbnRlcnNlY3QoZWwuZ2V0QkJveCgpLCBiYm94KSkge1xuICAgICAgICAgICAgICAgIHNldC5wdXNoKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBzZXQ7XG4gICAgfTtcblxuICAgIC8qXFxcbiAgICAgKiBQYXBlci5nZXRCeUlkXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHlvdSBlbGVtZW50IGJ5IGl0cyBpbnRlcm5hbCBJRC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gaWQgKG51bWJlcikgaWRcbiAgICAgPSAob2JqZWN0KSBSYXBoYcOrbCBlbGVtZW50IG9iamVjdFxuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmdldEJ5SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIGJvdCA9IHRoaXMuYm90dG9tO1xuICAgICAgICB3aGlsZSAoYm90KSB7XG4gICAgICAgICAgICBpZiAoYm90LmlkID09IGlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGJvdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJvdCA9IGJvdC5uZXh0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLmZvckVhY2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEV4ZWN1dGVzIGdpdmVuIGZ1bmN0aW9uIGZvciBlYWNoIGVsZW1lbnQgb24gdGhlIHBhcGVyXG4gICAgICpcbiAgICAgKiBJZiBjYWxsYmFjayBmdW5jdGlvbiByZXR1cm5zIGBmYWxzZWAgaXQgd2lsbCBzdG9wIGxvb3AgcnVubmluZy5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gY2FsbGJhY2sgKGZ1bmN0aW9uKSBmdW5jdGlvbiB0byBydW5cbiAgICAgLSB0aGlzQXJnIChvYmplY3QpIGNvbnRleHQgb2JqZWN0IGZvciB0aGUgY2FsbGJhY2tcbiAgICAgPSAob2JqZWN0KSBQYXBlciBvYmplY3RcbiAgICAgPiBVc2FnZVxuICAgICB8IHBhcGVyLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgIHwgICAgIGVsLmF0dHIoeyBzdHJva2U6IFwiYmx1ZVwiIH0pO1xuICAgICB8IH0pO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmZvckVhY2ggPSBmdW5jdGlvbiAoY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIGJvdCA9IHRoaXMuYm90dG9tO1xuICAgICAgICB3aGlsZSAoYm90KSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2suY2FsbCh0aGlzQXJnLCBib3QpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYm90ID0gYm90Lm5leHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0RWxlbWVudHNCeVBvaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHNldCBvZiBlbGVtZW50cyB0aGF0IGhhdmUgY29tbW9uIHBvaW50IGluc2lkZVxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgLSB5IChudW1iZXIpIHkgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcbiAgICAgPSAob2JqZWN0KSBAU2V0XG4gICAgXFwqL1xuICAgIHBhcGVycHJvdG8uZ2V0RWxlbWVudHNCeVBvaW50ID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgdmFyIHNldCA9IHRoaXMuc2V0KCk7XG4gICAgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbC5pc1BvaW50SW5zaWRlKHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgc2V0LnB1c2goZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHNldDtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHhfeSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueCArIFMgKyB0aGlzLnk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHhfeV93X2goKSB7XG4gICAgICAgI
57590HJldHVybiB0aGlzLnggKyBTICsgdGhpcy55ICsgUyArIHRoaXMud2lkdGggKyBcIiBcXHhkNyBcIiArIHRoaXMuaGVpZ2h0O1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5pc1BvaW50SW5zaWRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEZXRlcm1pbmUgaWYgZ2l2ZW4gcG9pbnQgaXMgaW5zaWRlIHRoaXMgZWxlbWVudOKAmXMgc2hhcGVcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBwb2ludCBpbnNpZGUgdGhlIHNoYXBlXG4gICAgXFwqL1xuICAgIGVscHJvdG8uaXNQb2ludEluc2lkZSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBycCA9IHRoaXMucmVhbFBhdGggPSBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmF0dHIoJ3RyYW5zZm9ybScpICYmIHRoaXMuYXR0cigndHJhbnNmb3JtJykubGVuZ3RoKSB7XG4gICAgICAgICAgICBycCA9IFIudHJhbnNmb3JtUGF0aChycCwgdGhpcy5hdHRyKCd0cmFuc2Zvcm0nKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFIuaXNQb2ludEluc2lkZVBhdGgocnAsIHgsIHkpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZ2V0QkJveFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmV0dXJuIGJvdW5kaW5nIGJveCBmb3IgYSBnaXZlbiBlbGVtZW50XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGlzV2l0aG91dFRyYW5zZm9ybSAoYm9vbGVhbikgZmxhZywgYHRydWVgIGlmIHlvdSB3YW50IHRvIGhhdmUgYm91bmRpbmcgYm94IGJlZm9yZSB0cmFuc2Zvcm1hdGlvbnMuIERlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICAgPSAob2JqZWN0KSBCb3VuZGluZyBib3ggb2JqZWN0OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgdG9wIGxlZnQgY29ybmVyIHhcbiAgICAgbyAgICAgeTogKG51bWJlcikgdG9wIGxlZnQgY29ybmVyIHlcbiAgICAgbyAgICAgeDI6IChudW1iZXIpIGJvdHRvbSByaWdodCBjb3JuZXIgeFxuICAgICBvICAgICB5MjogKG51bWJlcikgYm90dG9tIHJpZ2h0IGNvcm5lciB5XG4gICAgIG8gICAgIHdpZHRoOiAobnVtYmVyKSB3aWR0aFxuICAgICBvICAgICBoZWlnaHQ6IChudW1iZXIpIGhlaWdodFxuICAgICBvIH1cbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRCQm94ID0gZnVuY3Rpb24gKGlzV2l0aG91dFRyYW5zZm9ybSkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cbiAgICAgICAgdmFyIF8gPSB0aGlzLl87XG4gICAgICAgIGlmIChpc1dpdGhvdXRUcmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIGlmIChfLmRpcnR5IHx8ICFfLmJib3h3dCkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVhbFBhdGggPSBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgICAgICAgICAgXy5iYm94d3QgPSBwYXRoRGltZW5zaW9ucyh0aGlzLnJlYWxQYXRoKTtcbiAgICAgICAgICAgICAgICBfLmJib3h3dC50b1N0cmluZyA9IHhfeV93X2g7XG4gICAgICAgICAgICAgICAgXy5kaXJ0eSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gXy5iYm94d3Q7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF8uZGlydHkgfHwgXy5kaXJ0eVQgfHwgIV8uYmJveCkge1xuICAgICAgICAgICAgaWYgKF8uZGlydHkgfHwgIXRoaXMucmVhbFBhdGgpIHtcbiAgICAgICAgICAgICAgICBfLmJib3h3dCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFsUGF0aCA9IGdldFBhdGhbdGhpcy50eXBlXSh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF8uYmJveCA9IHBhdGhEaW1lbnNpb25zKG1hcFBhdGgodGhpcy5yZWFsUGF0aCwgdGhpcy5tYXRyaXgpKTtcbiAgICAgICAgICAgIF8uYmJveC50b1N0cmluZyA9IHhfeV93X2g7XG4gICAgICAgICAgICBfLmRpcnR5ID0gXy5kaXJ0eVQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfLmJib3g7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5jbG9uZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgY2xvbmUgb2YgYSBnaXZlbiBlbGVtZW50XG4gICAgICoqXG4gICAgXFwqL1xuICAgIGVscHJvdG8uY2xvbmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvdXQgPSB0aGlzLnBhcGVyW3RoaXMudHlwZV0oKS5hdHRyKHRoaXMuYXR0cigpKTtcbiAgICAgICAgdGhpcy5fX3NldF9fICYmIHRoaXMuX19zZXRfXy5wdXNoKG91dCk7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nbG93XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc2V0IG9mIGVsZW1lbnRzIHRoYXQgY3JlYXRlIGdsb3ctbGlrZSBlZmZlY3QgYXJvdW5kIGdpdmVuIGVsZW1lbnQuIFNlZSBAUGFwZXIuc2V0LlxuICAgICAqXG4gICAgICogTm90ZTogR2xvdyBpcyBub3QgY29ubmVjdGVkIHRvIHRoZSBlbGVtZW50LiBJZiB5b3UgY2hhbmdlIGVsZW1lbnQgYXR0cmlidXRlcyBpdCB3b27igJl0IGFkanVzdCBpdHNlbGYuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGdsb3cgKG9iamVjdCkgI29wdGlvbmFsIHBhcmFtZXRlcnMgb2JqZWN0IHdpdGggYWxsIHByb3BlcnRpZXMgb3B0aW9uYWw6XG4gICAgIG8ge1xuICAgICBvICAgICB3aWR0aCAobnVtYmVyKSBzaXplIG9mIHRoZSBnbG93LCBkZWZhdWx0IGlzIGAxMGBcbiAgICAgbyAgICAgZmlsbCAoYm9vbGVhbikgd2lsbCBpdCBiZSBmaWxsZWQsIGRlZmF1bHQgaXMgYGZhbHNlYFxuICAgICBvICAgICBvcGFjaXR5IChudW1iZXIpIG9wYWNpdHksIGRlZmF1bHQgaXMgYDAuNWBcbiAgICAgbyAgICAgb2Zmc2V0eCAobnVtYmVyKSBob3Jpem9udGFsIG9mZnNldCwgZGVmYXVsdCBpcyBgMGBcbiAgICAgbyAgICAgb2Zmc2V0eSAobnVtYmVyKSB2ZXJ0aWNhbCBvZmZzZXQsIGRlZmF1bHQgaXMgYDBgXG4gICAgIG8gICAgIGNvbG9yIChzdHJpbmcpIGdsb3cgY29sb3VyLCBkZWZhdWx0IGlzIGBibGFja2BcbiAgICAgbyB9XG4gICAgID0gKG9iamVjdCkgQFBhcGVyLnNldCBvZiBlbGVtZW50cyB0aGF0IHJlcHJlc2VudHMgZ2xvd1xuICAgIFxcKi9cbiAgICBlbHByb3RvLmdsb3cgPSBmdW5jdGlvbiAoZ2xvdykge1xuICAgICAgICBpZiAodGhpcy50eXBlID09IFwidGV4dFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBnbG93ID0gZ2xvdyB8fCB7fTtcbiAgICAgICAgdmFyIHMgPSB7XG4gICAgICAgICAgICB3aWR0aDogKGdsb3cud2lkdGggfHwgMTApICsgKCt0aGlzLmF0dHIoXCJzdHJva2Utd2lkdGhcIikgfHwgMSksXG4gICAgICAgICAgICBmaWxsOiBnbG93LmZpbGwgfHwgZmFsc2UsXG4gICAgICAgICAgICBvcGFjaXR5OiBnbG93Lm9wYWNpdHkgPT0gbnVsbCA/IC41IDogZ2xvdy5vcGFjaXR5LFxuICAgICAgICAgICAgb2Zmc2V0eDogZ2xvdy5vZmZzZXR4IHx8IDAsXG4gICAgICAgICAgICBvZmZzZXR5OiBnbG93Lm9mZnNldHkgfHwgMCxcbiAgICAgICAgICAgIGNvbG9yOiBnbG93Lm
57590NvbG9yIHx8IFwiIzAwMFwiXG4gICAgICAgIH0sXG4gICAgICAgICAgICBjID0gcy53aWR0aCAvIDIsXG4gICAgICAgICAgICByID0gdGhpcy5wYXBlcixcbiAgICAgICAgICAgIG91dCA9IHIuc2V0KCksXG4gICAgICAgICAgICBwYXRoID0gdGhpcy5yZWFsUGF0aCB8fCBnZXRQYXRoW3RoaXMudHlwZV0odGhpcyk7XG4gICAgICAgIHBhdGggPSB0aGlzLm1hdHJpeCA/IG1hcFBhdGgocGF0aCwgdGhpcy5tYXRyaXgpIDogcGF0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBjICsgMTsgaSsrKSB7XG4gICAgICAgICAgICBvdXQucHVzaChyLnBhdGgocGF0aCkuYXR0cih7XG4gICAgICAgICAgICAgICAgc3Ryb2tlOiBzLmNvbG9yLFxuICAgICAgICAgICAgICAgIGZpbGw6IHMuZmlsbCA/IHMuY29sb3IgOiBcIm5vbmVcIixcbiAgICAgICAgICAgICAgICBcInN0cm9rZS1saW5lam9pblwiOiBcInJvdW5kXCIsXG4gICAgICAgICAgICAgICAgXCJzdHJva2UtbGluZWNhcFwiOiBcInJvdW5kXCIsXG4gICAgICAgICAgICAgICAgXCJzdHJva2Utd2lkdGhcIjogKyhzLndpZHRoIC8gYyAqIGkpLnRvRml4ZWQoMyksXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogKyhzLm9wYWNpdHkgLyBjKS50b0ZpeGVkKDMpXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dC5pbnNlcnRCZWZvcmUodGhpcykudHJhbnNsYXRlKHMub2Zmc2V0eCwgcy5vZmZzZXR5KTtcbiAgICB9O1xuICAgIHZhciBjdXJ2ZXNsZW5ndGhzID0ge30sXG4gICAgZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGggPSBmdW5jdGlvbiAocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIGxlbmd0aCkge1xuICAgICAgICBpZiAobGVuZ3RoID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBiZXpsZW4ocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFIuZmluZERvdHNBdFNlZ21lbnQocDF4LCBwMXksIGMxeCwgYzF5LCBjMngsIGMyeSwgcDJ4LCBwMnksIGdldFRhdExlbihwMXgsIHAxeSwgYzF4LCBjMXksIGMyeCwgYzJ5LCBwMngsIHAyeSwgbGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldExlbmd0aEZhY3RvcnkgPSBmdW5jdGlvbiAoaXN0b3RhbCwgc3VicGF0aCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHBhdGgsIGxlbmd0aCwgb25seXN0YXJ0KSB7XG4gICAgICAgICAgICBwYXRoID0gcGF0aDJjdXJ2ZShwYXRoKTtcbiAgICAgICAgICAgIHZhciB4LCB5LCBwLCBsLCBzcCA9IFwiXCIsIHN1YnBhdGhzID0ge30sIHBvaW50LFxuICAgICAgICAgICAgICAgIGxlbiA9IDA7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBwYXRoLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwID0gcGF0aFtpXTtcbiAgICAgICAgICAgICAgICBpZiAocFswXSA9PSBcIk1cIikge1xuICAgICAgICAgICAgICAgICAgICB4ID0gK3BbMV07XG4gICAgICAgICAgICAgICAgICAgIHkgPSArcFsyXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsID0gZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGgoeCwgeSwgcFsxXSwgcFsyXSwgcFszXSwgcFs0XSwgcFs1XSwgcFs2XSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsZW4gKyBsID4gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3VicGF0aCAmJiAhc3VicGF0aHMuc3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludCA9IGdldFBvaW50QXRTZWdtZW50TGVuZ3RoKHgsIHksIHBbMV0sIHBbMl0sIHBbM10sIHBbNF0sIHBbNV0sIHBbNl0sIGxlbmd0aCAtIGxlbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3AgKz0gW1wiQ1wiICsgcG9pbnQuc3RhcnQueCwgcG9pbnQuc3RhcnQueSwgcG9pbnQubS54LCBwb2ludC5tLnksIHBvaW50LngsIHBvaW50LnldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvbmx5c3RhcnQpIHtyZXR1cm4gc3A7fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1YnBhdGhzLnN0YXJ0ID0gc3A7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3AgPSBbXCJNXCIgKyBwb2ludC54LCBwb2ludC55ICsgXCJDXCIgKyBwb2ludC5uLngsIHBvaW50Lm4ueSwgcG9pbnQuZW5kLngsIHBvaW50LmVuZC55LCBwWzVdLCBwWzZdXS5qb2luKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuICs9IGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICtwWzVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSArcFs2XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXN0b3RhbCAmJiAhc3VicGF0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ID0gZ2V0UG9pbnRBdFNlZ21lbnRMZW5ndGgoeCwgeSwgcFsxXSwgcFsyXSwgcFszXSwgcFs0XSwgcFs1XSwgcFs2XSwgbGVuZ3RoIC0gbGVuKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge3g6IHBvaW50LngsIHk6IHBvaW50LnksIGFscGhhOiBwb2ludC5hbHBoYX07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGVuICs9IGw7XG4gICAgICAgICAgICAgICAgICAgIHggPSArcFs1XTtcbiAgICAgICAgICAgICAgICAgICAgeSA9ICtwWzZdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzcCArPSBwLnNoaWZ0KCkgKyBwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3VicGF0aHMuZW5kID0gc3A7XG4gICAgICAgICAgICBwb2ludCA9IGlzdG90YWwgPyBsZW4gOiBzdWJwYXRoID8gc3VicGF0aHMgOiBSLmZpbmREb3RzQXRTZWdtZW50KHgsIHksIHBbMF0sIHBbMV0sIHBbMl0sIHBbM10sIHBbNF0sIHBbNV0sIDEpO1xuICAgICAgICAgICAgcG9pbnQuYWxwaGEgJiYgKHBvaW50ID0ge3g6IHBvaW50LngsIHk6IHBvaW50LnksIGFscGhhOiBwb2ludC5hbHBoYX0pO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50O1xuICAgICAgICB9O1xuICAgIH07XG4gICAgdmFyIGdldFRvdGFsTGVuZ3RoID0gZ2V0TGVuZ3RoRmFjdG9yeSgxKSxcbiAgICAgICAgZ2V0UG9pbnRBdExlbmd0aCA9IGdldExlbmd0aEZhY3RvcnkoKSxcbiAgICAgICAgZ2V0U3VicGF0aHNBdExlbmd0aCA9IGdldExlbmd0aEZhY3RvcnkoMCwgMSk7XG4gICAgLypcXFxuICAgICAqIFJhcGh
57590hZWwuZ2V0VG90YWxMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgbGVuZ3RoIG9mIHRoZSBnaXZlbiBwYXRoIGluIHBpeGVscy5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gcGF0aCAoc3RyaW5nKSBTVkcgcGF0aCBzdHJpbmcuXG4gICAgICoqXG4gICAgID0gKG51bWJlcikgbGVuZ3RoLlxuICAgIFxcKi9cbiAgICBSLmdldFRvdGFsTGVuZ3RoID0gZ2V0VG90YWxMZW5ndGg7XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuZ2V0UG9pbnRBdExlbmd0aFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmV0dXJuIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBsb2NhdGVkIGF0IHRoZSBnaXZlbiBsZW5ndGggb24gdGhlIGdpdmVuIHBhdGguXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIHBhdGggKHN0cmluZykgU1ZHIHBhdGggc3RyaW5nXG4gICAgIC0gbGVuZ3RoIChudW1iZXIpXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlXG4gICAgIG8gICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgZGVyaXZhdGl2ZVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgUi5nZXRQb2ludEF0TGVuZ3RoID0gZ2V0UG9pbnRBdExlbmd0aDtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5nZXRTdWJwYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc3VicGF0aCBvZiBhIGdpdmVuIHBhdGggZnJvbSBnaXZlbiBsZW5ndGggdG8gZ2l2ZW4gbGVuZ3RoLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXRoIChzdHJpbmcpIFNWRyBwYXRoIHN0cmluZ1xuICAgICAtIGZyb20gKG51bWJlcikgcG9zaXRpb24gb2YgdGhlIHN0YXJ0IG9mIHRoZSBzZWdtZW50XG4gICAgIC0gdG8gKG51bWJlcikgcG9zaXRpb24gb2YgdGhlIGVuZCBvZiB0aGUgc2VnbWVudFxuICAgICAqKlxuICAgICA9IChzdHJpbmcpIHBhdGhzdHJpbmcgZm9yIHRoZSBzZWdtZW50XG4gICAgXFwqL1xuICAgIFIuZ2V0U3VicGF0aCA9IGZ1bmN0aW9uIChwYXRoLCBmcm9tLCB0bykge1xuICAgICAgICBpZiAodGhpcy5nZXRUb3RhbExlbmd0aChwYXRoKSAtIHRvIDwgMWUtNikge1xuICAgICAgICAgICAgcmV0dXJuIGdldFN1YnBhdGhzQXRMZW5ndGgocGF0aCwgZnJvbSkuZW5kO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gZ2V0U3VicGF0aHNBdExlbmd0aChwYXRoLCB0bywgMSk7XG4gICAgICAgIHJldHVybiBmcm9tID8gZ2V0U3VicGF0aHNBdExlbmd0aChhLCBmcm9tKS5lbmQgOiBhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuZ2V0VG90YWxMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybnMgbGVuZ3RoIG9mIHRoZSBwYXRoIGluIHBpeGVscy4gT25seSB3b3JrcyBmb3IgZWxlbWVudCBvZiDigJxwYXRo4oCdIHR5cGUuXG4gICAgID0gKG51bWJlcikgbGVuZ3RoLlxuICAgIFxcKi9cbiAgICBlbHByb3RvLmdldFRvdGFsTGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2Y
57590XIgcGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICBpZiAoIXBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm5vZGUuZ2V0VG90YWxMZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5vZGUuZ2V0VG90YWxMZW5ndGgoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnZXRUb3RhbExlbmd0aChwYXRoKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LmdldFBvaW50QXRMZW5ndGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJldHVybiBjb29yZGluYXRlcyBvZiB0aGUgcG9pbnQgbG9jYXRlZCBhdCB0aGUgZ2l2ZW4gbGVuZ3RoIG9uIHRoZSBnaXZlbiBwYXRoLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50IG9mIOKAnHBhdGjigJ0gdHlwZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gbGVuZ3RoIChudW1iZXIpXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50OlxuICAgICBvIHtcbiAgICAgbyAgICAgeDogKG51bWJlcikgeCBjb29yZGluYXRlXG4gICAgIG8gICAgIHk6IChudW1iZXIpIHkgY29vcmRpbmF0ZVxuICAgICBvICAgICBhbHBoYTogKG51bWJlcikgYW5nbGUgb2YgZGVyaXZhdGl2ZVxuICAgICBvIH1cbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRQb2ludEF0TGVuZ3RoID0gZnVuY3Rpb24gKGxlbmd0aCkge1xuICAgICAgICB2YXIgcGF0aCA9IHRoaXMuZ2V0UGF0aCgpO1xuICAgICAgICBpZiAoIXBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBnZXRQb2ludEF0TGVuZ3RoKHBhdGgsIGxlbmd0aCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nZXRQYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIHBhdGggb2YgdGhlIGVsZW1lbnQuIE9ubHkgd29ya3MgZm9yIGVsZW1lbnRzIG9mIOKAnHBhdGjigJ0gdHlwZSBhbmQgc2ltcGxlIGVsZW1lbnRzIGxpa2UgY2lyY2xlLlxuICAgICA9IChvYmplY3QpIHBhdGhcbiAgICAgKipcbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRQYXRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2Y
57590XIgcGF0aCxcbiAgICAgICAgICAgIGdldFBhdGggPSBSLl9nZXRQYXRoW3RoaXMudHlwZV07XG5cbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PSBcInRleHRcIiB8fCB0aGlzLnR5cGUgPT0gXCJzZXRcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdldFBhdGgpIHtcbiAgICAgICAgICAgIHBhdGggPSBnZXRQYXRoKHRoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5nZXRTdWJwYXRoXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm4gc3VicGF0aCBvZiBhIGdpdmVuIGVsZW1lbnQgZnJvbSBnaXZlbiBsZW5ndGggdG8gZ2l2ZW4gbGVuZ3RoLiBPbmx5IHdvcmtzIGZvciBlbGVtZW50IG9mIOKAnHBhdGjigJ0gdHlwZS5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZnJvbSAobnVtYmVyKSBwb3NpdGlvbiBvZiB0aGUgc3RhcnQgb2YgdGhlIHNlZ21lbnRcbiAgICAgLSB0byAobnVtYmVyKSBwb3NpdGlvbiBvZiB0aGUgZW5kIG9mIHRoZSBzZWdtZW50XG4gICAgICoqXG4gICAgID0gKHN0cmluZykgcGF0aHN0cmluZyBmb3IgdGhlIHNlZ21lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5nZXRTdWJwYXRoID0gZnVuY3Rpb24gKGZyb20sIHRvKSB7XG4gICAgICAgIHZhciBwYXRoID0gdGhpcy5nZXRQYXRoKCk7XG4gICAgICAgIGlmICghcGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFIuZ2V0U3VicGF0aChwYXRoLCBmcm9tLCB0byk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXNcbiAgICAgWyBwcm9wZXJ0eSBdXG4gICAgICoqXG4gICAgICogT2JqZWN0IHRoYXQgY29udGFpbnMgZWFzaW5nIGZvcm11bGFzIGZvciBhbmltYXRpb24uIFlvdSBjb3VsZCBleHRlbmQgaXQgd2l0aCB5b3VyIG93bi4gQnkgZGVmYXVsdCBpdCBoYXMgZm9sbG93aW5nIGxpc3Qgb2YgZWFzaW5nOlxuICAgICAjIDx1bD5cbiAgICAgIyAgICAgPGxpPuKAnGxpbmVhcuKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJwmbHQ74oCdIG9yIOKAnGVhc2VJbuKAnSBvciDigJxlYXNlLWlu4oCdPC9saT5cbiAgICAgIyAgICAgPGxpPuKAnD7igJ0gb3Ig4oCcZWFzZU91dOKAnSBvciDigJxlYXNlLW91dOKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJwmbHQ7PuKAnSBvciDigJxlYXNlSW5PdXTigJ0gb3Ig4oCcZWFzZS1pbi1vdXTigJ08L2xpPlxuICAgICAjICAgICA8bGk+4oCcYmFja0lu4oCdIG9yIOKAnGJhY2staW7igJ08L2xpPlxuICAgICAjICAgICA8bGk+4oCcYmFja091dOKAnSBvciDigJxiYWNrLW91dOKAnTwvbGk+XG4gICAgICMgICAgIDxsaT7igJxlbGFzdGlj4oCdPC9saT5cbiAgICAgIyAgICAgPGxpPuKAnGJvdW5jZeKAnTwvbGk+XG4gICAgICMgPC91bD5cbiAgICAgIyA8cD5TZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL3JhcGhhZWxqcy5jb20vZWFzaW5nLmh0bWxcIj5FYXNpbmcgZGVtbzwvYT4uPC9wPlxuICAgIFxcKi9cbiAgICB2YXIgZWYgPSBSLmVhc2luZ19mb3JtdWxhcyA9IHtcbiAgICAgICAgbGluZWFyOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIH0sXG4gICAgICAgIFwiPFwiOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgcmV0dXJuIHBvdyhuLCAxLjcpO1xuICAgICAgICB9LFxuICAgICAgICBcIj5cIjogZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHJldHVybiBwb3cobiwgLjQ4KTtcbiAgICAgICAgfSxcbiAgICAgICAgXCI8PlwiOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgdmFyIHEgPSAuNDggLSBuIC8gMS4wNCxcbiAgICAgICAgICAgICAgICBRID0gbWF0aC5zcXJ0KC4xNzM0ICsgcSAqIHEpLFxuICAgICAgICAgICAgICAgIHggPSBRIC0gcSxcbiAgICAgICAgICAgICAgICBYID0gcG93KGFicyh4KSwgMSAvIDMpICogKHggPCAwID8gLTEgOiAxKSxcbiAgICAgICAgICAgICAgICB5ID0gLVEgLSBxLFxuICAgICAgICAgICAgICAgIFkgPSBwb3coYWJzKHkpLCAxIC8gMykgKiAoeSA8IDAgPyAtMSA6IDEpLFxuICAgICAgICAgICAgICAgIHQgPSBYICsgWSArIC41O1xuICAgICAgICAgICAgcmV0dXJuICgxIC0gdCkgKiAzICogdCAqIHQgKyB0ICogdCAqIHQ7XG4gICAgICAgIH0sXG4gICAgICAgIGJhY2tJbjogZnVuY3Rpb24gKG4pIHtcbiAgICAgICAgICAgIHZhciBzID0gMS43MDE1ODtcbiAgICAgICAgICAgIHJldHVybiBuICogbiAqICgocyArIDEpICogbiAtIHMpO1xuICAgICAgICB9LFxuICAgICAgICBiYWNrT3V0OiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgbiA9IG4gLSAxO1xuICAgICAgICAgICAgdmFyIHMgPSAxLjcwMTU4O1xuICAgICAgICAgICAgcmV0dXJuIG4gKiBuICogKChzICsgMSkgKiBuICsgcykgKyAxO1xuICAgICAgICB9LFxuICAgICAgICBlbGFzdGljOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgaWYgKG4gPT0gISFuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcG93KDIsIC0xMCAqIG4pICogbWF0aC5zaW4oKG4gLSAuMDc1KSAqICgyICogUEkpIC8gLjMpICsgMTtcbiAgICAgICAgfSxcbiAgICAgICAgYm91bmNlOiBmdW5jdGlvbiAobikge1xuICAgICAgICAgICAgdmFyIHMgPSA3LjU2MjUsXG4gICAgICAgICAgICAgICAgcCA9IDIuNzUsXG4gICAgICAgICAgICAgICAgbDtcbiAgICAgICAgICAgIGlmIChuIDwgKDEgLyBwKSkge1xuICAgICAgICAgICAgICAgIGwgPSBzICogbiAqIG47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChuIDwgKDIgLyBwKSkge1xuICAgICAgICAgICAgICAgICAgICBuIC09ICgxLjUgLyBwKTtcbiAgICAgICAgICAgICAgICAgICAgbCA9IHMgKiBuICogbiArIC43NTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAobiA8ICgyLjUgLyBwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbiAtPSAoMi4yNSAvIHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbCA9IHMgKiBuICogbiArIC45Mzc1O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbiAtPSAoMi42MjUgLyBwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGwgPSBzICogbiAqIG4gKyAuOTg0Mzc1O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGw7XG4gICAgICAgI
57590H1cbiAgICB9O1xuICAgIGVmLmVhc2VJbiA9IGVmW1wiZWFzZS1pblwiXSA9IGVmW1wiPFwiXTtcbiAgICBlZi5lYXNlT3V0ID0gZWZbXCJlYXNlLW91dFwiXSA9IGVmW1wiPlwiXTtcbiAgICBlZi5lYXNlSW5PdXQgPSBlZltcImVhc2UtaW4tb3V0XCJdID0gZWZbXCI8PlwiXTtcbiAgICBlZltcImJhY2staW5cIl0gPSBlZi5iYWNrSW47XG4gICAgZWZbXCJiYWNrLW91dFwiXSA9IGVmLmJhY2tPdXQ7XG5cbiAgICB2YXIgYW5pbWF0aW9uRWxlbWVudHMgPSBbXSxcbiAgICAgICAgcmVxdWVzdEFuaW1GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5vUmVxdWVzdEFuaW1hdGlvbkZyYW1lICAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZSAgICAgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDE2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgIGFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBOb3cgPSArbmV3IERhdGUsXG4gICAgICAgICAgICAgICAgbCA9IDA7XG4gICAgICAgICAgICBmb3IgKDsgbCA8IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgbCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGUgPSBhbmltYXRpb25FbGVtZW50c1tsXTtcbiAgICAgICAgICAgICAgICBpZiAoZS5lbC5yZW1vdmVkIHx8IGUucGF1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2Y
57590XIgdGltZSA9IE5vdyAtIGUuc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIG1zID0gZS5tcyxcbiAgICAgICAgICAgICAgICAgICAgZWFzaW5nID0gZS5lYXNpbmcsXG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBlLmZyb20sXG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPSBlLmRpZmYsXG4gICAgICAgICAgICAgICAgICAgIHRvID0gZS50byxcbiAgICAgICAgICAgICAgICAgICAgdCA9IGUudCxcbiAgICAgICAgICAgICAgICAgICAgdGhhdCA9IGUuZWwsXG4gICAgICAgICAgICAgICAgICAgIHNldCA9IHt9LFxuICAgICAgICAgICAgICAgICAgICBub3csXG4gICAgICAgICAgICAgICAgICAgIGluaXQgPSB7fSxcbiAgICAgICAgICAgICAgICAgICAga2V5O1xuICAgICAgICAgICAgICAgIGlmIChlLmluaXRzdGF0dXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZSA9IChlLmluaXRzdGF0dXMgKiBlLmFuaW0udG9wIC0gZS5wcmV2KSAvIChlLnBlcmNlbnQgLSBlLnByZXYpICogbXM7XG4gICAgICAgICAgICAgICAgICAgIGUuc3RhdHVzID0gZS5pbml0c3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZS5pbml0c3RhdHVzO1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3AgJiYgYW5pbWF0aW9uRWxlbWVudHMuc3BsaWNlKGwtLSwgMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdGF0dXMgPSAoZS5wcmV2ICsgKGUucGVyY2VudCAtIGUucHJldikgKiAodGltZSAvIG1zKSkgLyBlLmFuaW0udG9wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGltZSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0aW1lIDwgbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGVhc2luZyh0aW1lIC8gbXMpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyIGluIGZyb20pIGlmIChmcm9tW2hhc10oYXR0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXZhaWxhYmxlQW5pbUF0dHJzW2F0dHJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBudTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gK2Zyb21bYXR0cl0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJjb2xvdXJcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gXCJyZ2IoXCIgKyBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uciArIHBvcyAqIG1zICogZGlmZlthdHRyXS5yKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uZyArIHBvcyAqIG1zICogZGlmZlthdHRyXS5nKSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cHRvMjU1KHJvdW5kKGZyb21bYXR0cl0uYiArIHBvcyAqIG1zICogZGlmZlthdHRyXS5iKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXS5qb2luKFwiLFwiKSArIFwiKVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3cgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZnJvbVthdHRyXS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMSwgamogPSBmcm9tW2F0dHJdW2ldLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV1bal0gPSArZnJvbVthdHRyXVtpXVtqXSArIHBvcyAqIG1zICogZGlmZlthdHRyXVtpXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vd1tpXSA9IG5vd1tpXS5qb2luKFMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IG5vdy5qb2luKFMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidHJhbnNmb3JtXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkaWZmW2F0dHJdLnJlYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBmcm9tW2F0dHJdLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMSwgamogPSBmcm9tW2F0dHJdW2ldLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93W2ldW2pdID0gZnJvbVthdHRyXVtpXVtqXSArIHBvcyAqIG1zICogZGlmZlthdHRyXVtpXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57590XIgZ2V0ID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gK2Zyb21bYXR0cl1baV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm93ID0gW1tcInJcIiwgZ2V0KDIpLCAwLCAwXSwgW1widFwiLCBnZXQoMyksIGdldCg0KV0sIFtcInNcIiwgZ2V0KDApLCBnZXQoMSksIDAsIDBdXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtbXCJtXCIsIGdldCgwKSwgZ2V0KDEpLCBnZXQoMiksIGdldCgzKSwgZ2V0KDQpLCBnZXQoNSldXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3N2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyID09IFwiY2xpcC1yZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaSA9IDQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93W2ldID0gK2Zyb21bYXR0cl1baV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZyb20yID0gW11bY29uY2F0XShmcm9tW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkgPSB0aGF0LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbYXR0cl0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3dbaV0gPSArZnJvbTJbaV0gKyBwb3MgKiBtcyAqIGRpZmZbYXR0cl1baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRbYXR0cl0gPSBub3c7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhhdC5hdHRyKHNldCk7XG4gICAgICAgICAgICAgICAgICAgIChmdW5jdGlvbiAoaWQsIHRoYXQsIGFuaW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5mcmFtZS5cIiArIGlkLCB0aGF0LCBhbmltKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9KSh0aGF0LmlkLCB0aGF0LCBlLmFuaW0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIChmdW5jdGlvbihmLCBlbCwgYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmUoXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyBlbC5pZCwgZWwsIGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5maW5pc2guXCIgKyBlbC5pZCwgZWwsIGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFIuaXMoZiwgXCJmdW5jdGlvblwiKSAmJiBmLmNhbGwoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pKGUuY2FsbGJhY2ssIHRoYXQsIGUuYW5pbSk7XG4gICAgICAgICAgICAgICAgICAgIHRoYXQuYXR0cih0byk7XG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShsLS0sIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5yZXBlYXQgPiAxICYmICFlLm5leHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIHRvKSBpZiAodG9baGFzXShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdFtrZXldID0gZS50b3RhbE9yaWdpbltrZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZS5lbC5hdHRyKGluaXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGUuYW5pbSwgZS5lbCwgZS5hbmltLnBlcmNlbnRzWzBdLCBudWxsLCBlLnRvdGFsT3JpZ2luLCBlLnJlcGVhdCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLm5leHQgJiYgIWUuc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGUuYW5pbSwgZS5lbCwgZS5uZXh0LCBudWxsLCBlLnRvdGFsT3JpZ2luLCBlLnJlcGVhdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5sZW5ndGggJiYgcmVxdWVzdEFuaW1GcmFtZShhbmltYXRpb24pO1xuICAgICAgICB9LFxuICAgICAgICB1cHRvMjU1ID0gZnVuY3Rpb24gKGNvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3IgPiAyNTUgPyAyNTUgOiBjb2xvciA8IDAgPyAwIDogY29sb3I7XG4gICAgICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuYW5pbWF0ZVdpdGhcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFjdHMgc2ltaWxhciB0byBARWxlbWVudC5hbmltYXRlLCBidXQgZW5zdXJlIHRoYXQgZ2l2ZW4gYW5pbWF0aW9uIHJ1bnMgaW4gc3luYy
57590B3aXRoIGFub3RoZXIgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZWwgKG9iamVjdCkgZWxlbWVudCB0byBzeW5jIHdpdGhcbiAgICAgLSBhbmltIChvYmplY3QpIGFuaW1hdGlvbiB0byBzeW5jIHdpdGhcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgI29wdGlvbmFsIGZpbmFsIGF0dHJpYnV0ZXMgZm9yIHRoZSBlbGVtZW50LCBzZWUgYWxzbyBARWxlbWVudC5hdHRyXG4gICAgIC0gbXMgKG51bWJlcikgI29wdGlvbmFsIG51bWJlciBvZiBtaWxsaXNlY29uZHMgZm9yIGFuaW1hdGlvbiB0byBydW5cbiAgICAgLSBlYXNpbmcgKHN0cmluZykgI29wdGlvbmFsIGVhc2luZyB0eXBlLiBBY2NlcHQgb24gb2YgQFJhcGhhZWwuZWFzaW5nX2Zvcm11bGFzIG9yIENTUyBmb3JtYXQ6IGBjdWJpYyYjeDIwMTA7YmV6aWVyKFhYLCYjMTYwO1hYLCYjMTYwO1hYLCYjMTYwO1hYKWBcbiAgICAgLSBjYWxsYmFjayAoZnVuY3Rpb24pICNvcHRpb25hbCBjYWxsYmFjayBmdW5jdGlvbi4gV2lsbCBiZSBjYWxsZWQgYXQgdGhlIGVuZCBvZiBhbmltYXRpb24uXG4gICAgICogb3JcbiAgICAgLSBlbGVtZW50IChvYmplY3QpIGVsZW1lbnQgdG8gc3luYyB3aXRoXG4gICAgIC0gYW5pbSAob2JqZWN0KSBhbmltYXRpb24gdG8gc3luYyB3aXRoXG4gICAgIC0gYW5pbWF0aW9uIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0LCBzZWUgQFJhcGhhZWwuYW5pbWF0aW9uXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLmFuaW1hdGVXaXRoID0gZnVuY3Rpb24gKGVsLCBhbmltLCBwYXJhbXMsIG1zLCBlYXNpbmcsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcztcbiAgICAgICAgaWYgKGVsZW1lbnQucmVtb3ZlZCkge1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2suY2FsbChlbGVtZW50KTtcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gcGFyYW1zIGluc3RhbmNlb2YgQW5pbWF0aW9uID8gcGFyYW1zIDogUi5hbmltYXRpb24ocGFyYW1zLCBtcywgZWFzaW5nLCBjYWxsYmFjayksXG4gICAgICAgICAgICB4LCB5O1xuICAgICAgICBydW5BbmltYXRpb24oYSwgZWxlbWVudCwgYS5wZXJjZW50c1swXSwgbnVsbCwgZWxlbWVudC5hdHRyKCkpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoYW5pbWF0aW9uRWxlbWVudHNbaV0uYW5pbSA9PSBhbmltICYmIGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsID09IGVsKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uRWxlbWVudHNbaWkgLSAxXS5zdGFydCA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldLnN0YXJ0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgICAgICAvL1xuICAgICAgICAvL1xuICAgICAgICAvLyB2YXIgYSA9IHBhcmFtcyA/IFIuYW5pbWF0aW9uKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIDogYW5pbSxcbiAgICAgICAgLy8gICAgIHN0YXR1cyA9IGVsZW1lbnQuc3RhdHVzKGFuaW0pO1xuICAgICAgICAvLyByZXR1cm4gdGhpcy5hbmltYXRlKGEpLnN0YXR1cyhhLCBzdGF0dXMgKiBhbmltLm1zIC8gYS5tcyk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBDdWJpY0JlemllckF0VGltZSh0LCBwMXgsIHAxeSwgcDJ4LCBwMnksIGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBjeCA9IDMgKiBwMXgsXG4gICAgICAgICAgICBieCA9IDMgKiAocDJ4IC0gcDF4KSAtIGN4LFxuICAgICAgICAgICAgYXggPSAxIC0gY3ggLSBieCxcbiAgICAgICAgICAgIGN5ID0gMyAqIHAxeSxcbiAgICAgICAgICAgIGJ5ID0gMyAqIChwMnkgLSBwMXkpIC0gY3ksXG4gICAgICAgICAgICBheSA9IDEgLSBjeSAtIGJ5O1xuICAgICAgICBmdW5jdGlvbiBzYW1wbGVDdXJ2ZVgodCkge1xuICAgICAgICAgICAgcmV0dXJuICgoYXggKiB0ICsgYngpICogdCArIGN4KSAqIHQ7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gc29sdmUoeCwgZXBzaWxvbikge1xuICAgICAgICAgICAgdmFyIHQgPSBzb2x2ZUN1cnZlWCh4LCBlcHNpbG9uKTtcbiAgICAgICAgICAgIHJldHVybiAoKGF5ICogdCArIGJ5KSAqIHQgKyBjeSkgKiB0O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHNvbHZlQ3VydmVYKHgsIGVwc2lsb24pIHtcbiAgICAgICAgICAgIHZhciB0MCwgdDEsIHQyLCB4MiwgZDIsIGk7XG4gICAgICAgICAgICBmb3IodDIgPSB4LCBpID0gMDsgaSA8IDg7IGkrKykge1xuICAgICAgICAgICAgICAgIHgyID0gc2FtcGxlQ3VydmVYKHQyKSAtIHg7XG4gICAgICAgICAgICAgICAgaWYgKGFicyh4MikgPCBlcHNpbG9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0MjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZDIgPSAoMyAqIGF4ICogdDIgKyAyICogYngpICogdDIgKyBjeDtcbiAgICAgICAgICAgICAgICBpZiAoYWJzKGQyKSA8IDFlLTYpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHQyID0gdDIgLSB4MiAvIGQyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdDAgPSAwO1xuICAgICAgICAgICAgdDEgPSAxO1xuICAgICAgICAgICAgdDIgPSB4O1xuICAgICAgICAgICAgaWYgKHQyIDwgdDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodDIgPiB0MSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0MTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlICh0MCA8IHQxKSB7XG4gICAgICAgICAgICAgICAgeDIgPSBzYW1wbGVDdXJ2ZVgodDIpO1xuICAgICAgICAgICAgICAgIGlmIChhYnMoeDIgLSB4KSA8IGVwc2lsb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHQyO
575901xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoeCA+IHgyKSB7XG4gICAgICAgICAgICAgICAgICAgIHQwID0gdDI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdDEgPSB0MjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdDIgPSAodDEgLSB0MCkgLyAyICsgdDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdDI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvbHZlKHQsIDEgLyAoMjAwICogZHVyYXRpb24pKTtcbiAgICB9XG4gICAgZWxwcm90by5vbkFuaW1hdGlvbiA9IGZ1bmN0aW9uIChmKSB7XG4gICAgICAgIGYgPyBldmUub24oXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyB0aGlzLmlkLCBmKSA6IGV2ZS51bmJpbmQoXCJyYXBoYWVsLmFuaW0uZnJhbWUuXCIgKyB0aGlzLmlkKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBBbmltYXRpb24oYW5pbSwgbXMpIHtcbiAgICAgICAgdmFyIHBlcmNlbnRzID0gW10sXG4gICAgICAgICAgICBuZXdBbmltID0ge307XG4gICAgICAgIHRoaXMubXMgPSBtcztcbiAgICAgICAgdGhpcy50aW1lcyA9IDE7XG4gICAgICAgIGlmIChhbmltKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBhdHRyIGluIGFuaW0pIGlmIChhbmltW2hhc10oYXR0cikpIHtcbiAgICAgICAgICAgICAgICBuZXdBbmltW3RvRmxvYXQoYXR0cildID0gYW5pbVthdHRyXTtcbiAgICAgICAgICAgICAgICBwZXJjZW50cy5wdXNoKHRvRmxvYXQoYXR0cikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGVyY2VudHMuc29ydChzb3J0QnlOdW1iZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYW5pbSA9IG5ld0FuaW07XG4gICAgICAgIHRoaXMudG9wID0gcGVyY2VudHNbcGVyY2VudHMubGVuZ3RoIC0gMV07XG4gICAgICAgIHRoaXMucGVyY2VudHMgPSBwZXJjZW50cztcbiAgICB9XG4gICAgLypcXFxuICAgICAqIEFuaW1hdGlvbi5kZWxheVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ3JlYXRlcyBhIGNvcHkgb2YgZXhpc3RpbmcgYW5pbWF0aW9uIG9iamVjdCB3aXRoIGdpdmVuIGRlbGF5LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBkZWxheSAobnVtYmVyKSBudW1iZXIgb2YgbXMgdG8gcGFzcyBiZXR3ZWVuIGFuaW1hdGlvbiBzdGFydCBhbmQgYWN0dWFsIGFuaW1hdGlvblxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG5ldyBhbHRlcmVkIEFuaW1hdGlvbiBvYmplY3RcbiAgICAgfCB2YXIgYW5pbSA9IFJhcGhhZWwuYW5pbWF0aW9uKHtjeDogMTAsIGN5OiAyMH0sIDJlMyk7XG4gICAgI
57590HwgY2lyY2xlMS5hbmltYXRlKGFuaW0pOyAvLyBydW4gdGhlIGdpdmVuIGFuaW1hdGlvbiBpbW1lZGlhdGVseVxuICAgICB8IGNpcmNsZTIuYW5pbWF0ZShhbmltLmRlbGF5KDUwMCkpOyAvLyBydW4gdGhlIGdpdmVuIGFuaW1hdGlvbiBhZnRlciA1MDAgbXNcbiAgICBcXCovXG4gICAgQW5pbWF0aW9uLnByb3RvdHlwZS5kZWxheSA9IGZ1bmN0aW9uIChkZWxheSkge1xuICAgICAgICB2YXIgYSA9IG5ldyBBbmltYXRpb24odGhpcy5hbmltLCB0aGlzLm1zKTtcbiAgICAgICAgYS50aW1lcyA9IHRoaXMudGltZXM7XG4gICAgICAgIGEuZGVsID0gK2RlbGF5IHx8IDA7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEFuaW1hdGlvbi5yZXBlYXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIGV4aXN0aW5nIGFuaW1hdGlvbiBvYmplY3Qgd2l0aCBnaXZlbiByZXBldGl0aW9uLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSByZXBlYXQgKG51bWJlcikgbnVtYmVyIGl0ZXJhdGlvbnMgb2YgYW5pbWF0aW9uLiBGb3IgaW5maW5pdGUgYW5pbWF0aW9uIHBhc3MgYEluZmluaXR5YFxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG5ldyBhbHRlcmVkIEFuaW1hdGlvbiBvYmplY3RcbiAgICBcXCovXG4gICAgQW5pbWF0aW9uLnByb3RvdHlwZS5yZXBlYXQgPSBmdW5jdGlvbiAodGltZXMpIHtcbiAgICAgICAgdmFyIGEgPSBuZXcgQW5pbWF0aW9uKHRoaXMuYW5pbSwgdGhpcy5tcyk7XG4gICAgICAgIGEuZGVsID0gdGhpcy5kZWw7XG4gICAgICAgIGEudGltZXMgPSBtYXRoLmZsb29yKG1tYXgodGltZXMsIDApKSB8fCAxO1xuICAgICAgICByZXR1cm4gYTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJ1bkFuaW1hdGlvbihhbmltLCBlbGVtZW50LCBwZXJjZW50LCBzdGF0dXMsIHRvdGFsT3JpZ2luLCB0aW1lcykge1xuICAgICAgICBwZXJjZW50ID0gdG9GbG9hdChwZXJjZW50KTtcbiAgICAgICAgdmFyIHBhcmFtcyxcbiAgICAgICAgICAgIGlzSW5BbmltLFxuICAgICAgICAgICAgaXNJbkFuaW1TZXQsXG4gICAgICAgICAgICBwZXJjZW50cyA9IFtdLFxuICAgICAgICAgICAgbmV4dCxcbiAgICAgICAgICAgIHByZXYsXG4gICAgICAgICAgICB0aW1lc3RhbXAsXG4gICAgICAgICAgICBtcyA9IGFuaW0ubXMsXG4gICAgICAgICAgICBmcm9tID0ge30sXG4gICAgICAgICAgICB0byA9IHt9LFxuICAgICAgICAgICAgZGlmZiA9IHt9O1xuICAgICAgICBpZiAoc3RhdHVzKSB7XG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2Y
57590XIgZSA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChlLmVsLmlkID09IGVsZW1lbnQuaWQgJiYgZS5hbmltID09IGFuaW0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUucGVyY2VudCAhPSBwZXJjZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0luQW5pbVNldCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc0luQW5pbSA9IGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hdHRyKGUudG90YWxPcmlnaW4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0dXMgPSArdG87IC8vIE5hTlxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGFuaW0ucGVyY2VudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgaWYgKGFuaW0ucGVyY2VudHNbaV0gPT0gcGVyY2VudCB8fCBhbmltLnBlcmNlbnRzW2ldID4gc3RhdHVzICogYW5pbS50b3ApIHtcbiAgICAgICAgICAgICAgICBwZXJjZW50ID0gYW5pbS5wZXJjZW50c1tpXTtcbiAgICAgICAgICAgICAgICBwcmV2ID0gYW5pbS5wZXJjZW50c1tpIC0gMV0gfHwgMDtcbiAgICAgICAgICAgICAgICBtcyA9IG1zIC8gYW5pbS50b3AgKiAocGVyY2VudCAtIHByZXYpO1xuICAgICAgICAgICAgICAgIG5leHQgPSBhbmltLnBlcmNlbnRzW2kgKyAxXTtcbiAgICAgICAgICAgICAgICBwYXJhbXMgPSBhbmltLmFuaW1bcGVyY2VudF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXR1cykge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXR0cihhbmltLmFuaW1bYW5pbS5wZXJjZW50c1tpXV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghcGFyYW1zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0luQW5pbSkge1xuICAgICAgICAgICAgZm9yICh2YXIgYXR0ciBpbiBwYXJhbXMpIGlmIChwYXJhbXNbaGFzXShhdHRyKSkge1xuICAgICAgICAgICAgICAgIGlmIChhdmFpbGFibGVBbmltQXR0cnNbaGFzXShhdHRyKSB8fCBlbGVtZW50LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShhdHRyKSkge1xuICAgICAgICAgICAgICAgICAgICBmcm9tW2F0dHJdID0gZWxlbWVudC5hdHRyKGF0dHIpO1xuICAgICAgICAgICAgICAgICAgICAoZnJvbVthdHRyXSA9PSBudWxsKSAmJiAoZnJvbVthdHRyXSA9IGF2YWlsYWJsZUF0dHJzW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgdG9bYXR0cl0gPSBwYXJhbXNbYXR0cl07XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXZhaWxhYmxlQW5pbUF0dHJzW2F0dHJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIG51OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl0gPSAodG9bYXR0cl0gLSBmcm9tW2F0dHJdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNvbG91clwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBSLmdldFJHQihmcm9tW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57590XIgdG9Db2xvdXIgPSBSLmdldFJHQih0b1thdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcjogKHRvQ29sb3VyLnIgLSBmcm9tW2F0dHJdLnIpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGc6ICh0b0NvbG91ci5nIC0gZnJvbVthdHRyXS5nKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiOiAodG9Db2xvdXIuYiAtIGZyb21bYXR0cl0uYikgLyBtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXRoZXMgPSBwYXRoMmN1cnZlKGZyb21bYXR0cl0sIHRvW2F0dHJdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9QYXRoID0gcGF0aGVzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBwYXRoZXNbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gZnJvbVthdHRyXS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV0gPSBbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAxLCBqaiA9IGZyb21bYXR0cl1baV0ubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXVtpXVtqXSA9ICh0b1BhdGhbaV1bal0gLSBmcm9tW2F0dHJdW2ldW2pdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInRyYW5zZm9ybVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfID0gZWxlbWVudC5fLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcSA9IGVxdWFsaXNlVHJhbnNmb3JtKF9bYXR0cl0sIHRvW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbVthdHRyXSA9IGVxLmZyb207XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvW2F0dHJdID0gZXEudG87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXS5yZWFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBmcm9tW2F0dHJdLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV0gPSBbZnJvbVthdHRyXVtpXVswXV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAxLCBqaiA9IGZyb21bYXR0cl1baV0ubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYXR0cl1baV1bal0gPSAodG9bYXR0cl1baV1bal0gLSBmcm9tW2F0dHJdW2ldW2pdKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG0gPSAoZWxlbWVudC5tYXRyaXggfHwgbmV3IE1hdHJpeCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bzIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXzoge3RyYW5zZm9ybTogXy50cmFuc2Zvcm19LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEJCb3g6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tW2F0dHJdID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5hLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5iLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5jLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5kLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbS5mXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dHJhY3RUcmFuc2Zvcm0odG8yLCB0b1thdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvW2F0dHJdID0gdG8yLl8udHJhbnNmb3JtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2F0dHJdID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRvMi5tYXRyaXguYSAtIG0uYSkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0bzIubWF0cml4LmIgLSBtLmIpIC8gbX
57590MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodG8yLm1hdHJpeC5jIC0gbS5jKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRvMi5tYXRyaXguZCAtIG0uZCkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh0bzIubWF0cml4LmUgLSBtLmUpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodG8yLm1hdHJpeC5mIC0gbS5mKSAvIG1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZyb21bYXR0cl0gPSBbXy5zeCwgXy5zeSwgXy5kZWcsIF8uZHgsIF8uZHldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB2YXIgdG8yID0ge186e30sIGdldEJCb3g6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGVsZW1lbnQuZ2V0QkJveCgpOyB9fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXh0cmFjdFRyYW5zZm9ybSh0bzIsIHRvW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZGlmZlthdHRyXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICh0bzIuXy5zeCAtIF8uc3gpIC8gbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAodG8yLl8uc3kgLSBfLnN5KSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKHRvMi5fLmRlZyAtIF8uZGVnKSAvIG1zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgKHRvMi5fLmR4IC0gXy5keCkgLyBtcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICh0bzIuXy5keSAtIF8uZHkpIC8gbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3N2XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFN0cihwYXJhbXNbYXR0cl0pW3NwbGl0XShzZXBhcmF0b3IpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tMiA9IFN0cihmcm9tW2F0dHJdKVtzcGxpdF0oc2VwYXJhdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ciA9PSBcImNsaXAtcmVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb21bYXR0cl0gPSBmcm9tMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpID0gZnJvbTIubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2F0dHJdW2ldID0gKHZhbHVlc1tpXSAtIGZyb21bYXR0cl1baV0pIC8gbXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9bYXR0cl0gPSB2YWx1ZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IFtdW2NvbmNhdF0ocGFyYW1zW2F0dHJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9tMiA9IFtdW2NvbmNhdF0oZnJvbVthdHRyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGkgPSBlbGVtZW50LnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbYXR0cl0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthdHRyXVtpXSA9ICgodmFsdWVzW2ldIHx8IDApIC0gKGZyb20yW2ldIHx8IDApKSAvIG1zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBlYXNpbmcgPSBwYXJhbXMuZWFzaW5nLFxuICAgICAgICAgICAgICAgIGVhc3llYXN5ID0gUi5lYXNpbmdfZm9ybXVsYXNbZWFzaW5nXTtcbiAgICAgICAgICAgIGlmICghZWFzeWVhc3kpIHtcbiAgICAgICAgICAgICAgICBlYXN5ZWFzeSA9IFN0cihlYXNpbmcpLm1hdGNoKGJlemllcnJnKTtcbiAgICAgICAgICAgICAgICBpZiAoZWFzeWVhc3kgJiYgZWFzeWVhc3kubGVuZ3RoID09IDUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnZlID0gZWFzeWVhc3k7XG4gICAgICAgICAgICAgICAgICAgIGVhc3llYXN5ID0gZnVuY3Rpb24gKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBDdWJpY0JlemllckF0VGltZSh0LCArY3VydmVbMV0sICtjdXJ2ZVsyXSwgK2N1cnZlWzNdLCArY3VydmVbNF0sIG1zKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlYXN5ZWFzeSA9IHBpcGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGltZXN0YW1wID0gcGFyYW1zLnN0YXJ0IHx8IGFuaW0uc3RhcnQgfHwgK25ldyBEYXRlO1xuICAgICAgICAgICAgZSA9IHtcbiAgICAgICAgICAgICAgICBhbmltOiBhbmltLFxuICAgICAgICAgICAgICAgIHBlcmNlbnQ6IHBlcmNlbnQsXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiB0aW1lc3RhbXAsXG4gICAgICAgICAgICAgICAgc3RhcnQ6IHRpbWVzdGFtcCArIChhbmltLmRlbCB8fCAwKSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IDAsXG4gICAgICAgICAgICAgICAgaW5pdHN0YXR1czogc3Rh
57590dHVzIHx8IDAsXG4gICAgICAgICAgICAgICAgc3RvcDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbXM6IG1zLFxuICAgICAgICAgICAgICAgIGVhc2luZzogZWFzeWVhc3ksXG4gICAgICAgICAgICAgICAgZnJvbTogZnJvbSxcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHRvOiB0byxcbiAgICAgICAgICAgICAgICBlbDogZWxlbWVudCxcbiAgICAgICAgICAgICAgICBjYWxsYmFjazogcGFyYW1zLmNhbGxiYWNrLFxuICAgICAgICAgICAgICAgIHByZXY6IHByZXYsXG4gICAgICAgICAgICAgICAgbmV4dDogbmV4dCxcbiAgICAgICAgICAgICAgICByZXBlYXQ6IHRpbWVzIHx8IGFuaW0udGltZXMsXG4gICAgICAgICAgICAgICAgb3JpZ2luOiBlbGVtZW50LmF0dHIoKSxcbiAgICAgICAgICAgICAgICB0b3RhbE9yaWdpbjogdG90YWxPcmlnaW5cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5wdXNoKGUpO1xuICAgICAgICAgICAgaWYgKHN0YXR1cyAmJiAhaXNJbkFuaW0gJiYgIWlzSW5BbmltU2V0KSB7XG4gICAgICAgICAgICAgICAgZS5zdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBlLnN0YXJ0ID0gbmV3IERhdGUgLSBtcyAqIHN0YXR1cztcbiAgICAgICAgICAgICAgICBpZiAoYW5pbWF0aW9uRWxlbWVudHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFuaW1hdGlvbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0luQW5pbVNldCkge1xuICAgICAgICAgICAgICAgIGUuc3RhcnQgPSBuZXcgRGF0ZSAtIGUubXMgKiBzdGF0dXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhbmltYXRpb25FbGVtZW50cy5sZW5ndGggPT0gMSAmJiByZXF1ZXN0QW5pbUZyYW1lKGFuaW1hdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc0luQW5pbS5pbml0c3RhdHVzID0gc3RhdHVzO1xuICAgICAgICAgICAgaXNJbkFuaW0uc3RhcnQgPSBuZXcgRGF0ZSAtIGlzSW5BbmltLm1zICogc3RhdHVzO1xuICAgICAgICB9XG4gICAgICAgIGV2ZShcInJhcGhhZWwuYW5pbS5zdGFydC5cIiArIGVsZW1lbnQuaWQsIGVsZW1lbnQsIGFuaW0pO1xuICAgIH1cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5hbmltYXRpb25cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENyZWF0ZXMgYW4gYW5pbWF0aW9uIG9iamVjdCB0aGF0IGNhbiBiZSBwYXNzZWQgdG8gdGhlIEBFbGVtZW50LmFuaW1hdGUgb3IgQEVsZW1lbnQuYW5pbWF0ZVdpdGggbWV0aG9kcy5cbiAgICAgKiBTZWUgYWxzbyBAQW5pbWF0aW9uLmRlbGF5IGFuZCBAQW5pbWF0aW9uLnJlcGVhdCBtZXRob2RzLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgZmluYWwgYXR0cmlidXRlcyBmb3IgdGhlIGVsZW1lbnQsIHNlZSBhbHNvIEBFbGVtZW50LmF0dHJcbiAgICAgLSBtcyAobnVtYmVyKSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGZvciBhbmltYXRpb24gdG8gcnVuXG4gICAgIC0gZWFzaW5nIChzdHJpbmcpICNvcHRpb25hbCBlYXNpbmcgdHlwZS4gQWNjZXB0IG9uZSBvZiBAUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXMgb3IgQ1NTIGZvcm1hdDogYGN1YmljJiN4MjAxMDtiZXppZXIoWFgsJiMxNjA7WFgsJiMxNjA7WFgsJiMxNjA7WFgpYFxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uLiBXaWxsIGJlIGNhbGxlZCBhdCB0aGUgZW5kIG9mIGFuaW1hdGlvbi5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBAQW5pbWF0aW9uXG4gICAgXFwqL1xuICAgIFIuYW5pbWF0aW9uID0gZnVuY3Rpb24gKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHBhcmFtcyBpbnN0YW5jZW9mIEFuaW1hdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICAgICAgfVxuICAgICAgICBpZiAoUi5pcyhlYXNpbmcsIFwiZnVuY3Rpb25cIikgfHwgIWVhc2luZykge1xuICAgICAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBlYXNpbmcgfHwgbnVsbDtcbiAgICAgICAgICAgIGVhc2luZyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1zID0gT2JqZWN0KHBhcmFtcyk7XG4gICAgICAgIG1zID0gK21zIHx8IDA7XG4gICAgICAgIHZhciBwID0ge30sXG4gICAgICAgICAgICBqc29uLFxuICAgICAgICAgICAgYXR0cjtcbiAgICAgICAgZm9yIChhdHRyIGluIHBhcmFtcykgaWYgKHBhcmFtc1toYXNdKGF0dHIpICYmIHRvRmxvYXQoYXR0cikgIT0gYXR0ciAmJiB0b0Zsb2F0KGF0dHIpICsgXCIlXCIgIT0gYXR0cikge1xuICAgICAgICAgICAganNvbiA9IHRydWU7XG4gICAgICAgICAgICBwW2F0dHJdID0gcGFyYW1zW2F0dHJdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghanNvbikge1xuICAgICAgICAgICAgLy8gaWYgcGVyY2VudC1saWtlIHN5bnRheCBpcyB1c2VkIGFuZCBlbmQtb2YtYWxsIGFuaW1hdGlvbiBjYWxsYmFjayB1c2VkXG4gICAgICAgICAgICBpZihjYWxsYmFjayl7XG4gICAgICAgICAgICAgICAgLy8gZmluZCB0aGUgbGFzdCBvbmVcbiAgICAgICAgICAgICAgICB2Y
57590XIgbGFzdEtleSA9IDA7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpIGluIHBhcmFtcyl7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwZXJjZW50ID0gdG9JbnQoaSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHBhcmFtc1toYXNdKGkpICYmIHBlcmNlbnQgPiBsYXN0S2V5KXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RLZXkgPSBwZXJjZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxhc3RLZXkgKz0gJyUnO1xuICAgICAgICAgICAgICAgIC8vIGlmIGFscmVhZHkgZGVmaW5lZCBjYWxsYmFjayBpbiB0aGUgbGFzdCBrZXlmcmFtZSwgc2tpcFxuICAgICAgICAgICAgICAgICFwYXJhbXNbbGFzdEtleV0uY2FsbGJhY2sgJiYgKHBhcmFtc1tsYXN0S2V5XS5jYWxsYmFjayA9IGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV3IEFuaW1hdGlvbihwYXJhbXMsIG1zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVhc2luZyAmJiAocC5lYXNpbmcgPSBlYXNpbmcpO1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgKHAuY2FsbGJhY2sgPSBjYWxsYmFjayk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEFuaW1hdGlvbih7MTAwOiBwfSwgbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5hbmltYXRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIGFuZCBzdGFydHMgYW5pbWF0aW9uIGZvciBnaXZlbiBlbGVtZW50LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBwYXJhbXMgKG9iamVjdCkgZmluYWwgYXR0cmlidXRlcyBmb3IgdGhlIGVsZW1lbnQsIHNlZSBhbHNvIEBFbGVtZW50LmF0dHJcbiAgICAgLSBtcyAobnVtYmVyKSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGZvciBhbmltYXRpb24gdG8gcnVuXG4gICAgIC0gZWFzaW5nIChzdHJpbmcpICNvcHRpb25hbCBlYXNpbmcgdHlwZS4gQWNjZXB0IG9uZSBvZiBAUmFwaGFlbC5lYXNpbmdfZm9ybXVsYXMgb3IgQ1NTIGZvcm1hdDogYGN1YmljJiN4MjAxMDtiZXppZXIoWFgsJiMxNjA7WFgsJiMxNjA7WFgsJiMxNjA7WFgpYFxuICAgICAtIGNhbGxiYWNrIChmdW5jdGlvbikgI29wdGlvbmFsIGNhbGxiYWNrIGZ1bmN0aW9uLiBXaWxsIGJlIGNhbGxlZCBhdCB0aGUgZW5kIG9mIGFuaW1hdGlvbi5cbiAgICAgKiBvclxuICAgICAtIGFuaW1hdGlvbiAob2JqZWN0KSBhbmltYXRpb24gb2JqZWN0LCBzZWUgQFJhcGhhZWwuYW5pbWF0aW9uXG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLmFuaW1hdGUgPSBmdW5jdGlvbiAocGFyYW1zLCBtcywgZWFzaW5nLCBjYWxsYmFjaykge1xuICAgICAgICB2Y
57590XIgZWxlbWVudCA9IHRoaXM7XG4gICAgICAgIGlmIChlbGVtZW50LnJlbW92ZWQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrLmNhbGwoZWxlbWVudCk7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYW5pbSA9IHBhcmFtcyBpbnN0YW5jZW9mIEFuaW1hdGlvbiA/IHBhcmFtcyA6IFIuYW5pbWF0aW9uKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spO1xuICAgICAgICBydW5BbmltYXRpb24oYW5pbSwgZWxlbWVudCwgYW5pbS5wZXJjZW50c1swXSwgbnVsbCwgZWxlbWVudC5hdHRyKCkpO1xuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnNldFRpbWVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNldHMgdGhlIHN0YXR1cyBvZiBhbmltYXRpb24gb2YgdGhlIGVsZW1lbnQgaW4gbWlsbGlzZWNvbmRzLiBTaW1pbGFyIHRvIEBFbGVtZW50LnN0YXR1cyBtZXRob2QuXG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGFuaW0gKG9iamVjdCkgYW5pbWF0aW9uIG9iamVjdFxuICAgICAtIHZhbHVlIChudW1iZXIpIG51bWJlciBvZiBtaWxsaXNlY29uZHMgZnJvbSB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhbmltYXRpb25cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBvcmlnaW5hbCBlbGVtZW50IGlmIGB2YWx1ZWAgaXMgc3BlY2lmaWVkXG4gICAgICogTm90ZSwgdGhhdCBkdXJpbmcgYW5pbWF0aW9uIGZvbGxvd2luZyBldmVudHMgYXJlIHRyaWdnZXJlZDpcbiAgICAgKlxuICAgICAqIE9uIGVhY2ggYW5pbWF0aW9uIGZyYW1lIGV2ZW50IGBhbmltLmZyYW1lLjxpZD5gLCBvbiBzdGFydCBgYW5pbS5zdGFydC48aWQ+YCBhbmQgb24gZW5kIGBhbmltLmZpbmlzaC48aWQ+YC5cbiAgICBcXCovXG4gICAgZWxwcm90by5zZXRUaW1lID0gZnVuY3Rpb24gKGFuaW0sIHZhbHVlKSB7XG4gICAgICAgIGlmIChhbmltICYmIHZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhdHVzKGFuaW0sIG1taW4odmFsdWUsIGFuaW0ubXMpIC8gYW5pbS5tcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5zdGF0dXNcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEdldHMgb3Igc2V0cyB0aGUgc3RhdHVzIG9mIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gYW5pbSAob2JqZWN0KSAjb3B0aW9uYWwgYW5pbWF0aW9uIG9iamVjdFxuICAgICAtIHZhbHVlIChudW1iZXIpICNvcHRpb25hbCAwIOKAkyAxLiBJZiBzcGVjaWZpZWQsIG1ldGhvZCB3b3JrcyBsaWtlIGEgc2V0dGVyIGFuZCBzZXRzIHRoZSBzdGF0dXMgb2YgYSBnaXZlbiBhbmltYXRpb24gdG8gdGhlIHZhbHVlLiBUaGlzIHdpbGwgY2F1c2UgYW5pbWF0aW9uIHRvIGp1bXAgdG8gdGhlIGdpdmVuIHBvc2l0aW9uLlxuICAgICAqKlxuICAgICA9IChudW1iZXIpIHN0YXR1c1xuICAgICAqIG9yXG4gICAgID0gKGFycmF5KSBzdGF0dXMgaWYgYGFuaW1gIGlzIG5vdCBzcGVjaWZpZWQuIEFycmF5IG9mIG9iamVjdHMgaW4gZm9ybWF0OlxuICAgICBvIHtcbiAgICAgbyAgICAgYW5pbTogKG9iamVjdCkgYW5pbWF0aW9uIG9iamVjdFxuICAgICBvICAgICBzdGF0dXM6IChudW1iZXIpIHN0YXR1c1xuICAgICBvIH1cbiAgICAgKiBvclxuICAgICA9IChvYmplY3QpIG9yaWdpbmFsIGVsZW1lbnQgaWYgYHZhbHVlYCBpcyBzcGVjaWZpZWRcbiAgICBcXCovXG4gICAgZWxwcm90by5zdGF0dXMgPSBmdW5jdGlvbiAoYW5pbSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIG91dCA9IFtdLFxuICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICBsZW4sXG4gICAgICAgICAgICBlO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcnVuQW5pbWF0aW9uKGFuaW0sIHRoaXMsIC0xLCBtbWluKHZhbHVlLCAxKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlbiA9IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBlID0gYW5pbWF0aW9uRWxlbWVudHNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGUuZWwuaWQgPT0gdGhpcy5pZCAmJiAoIWFuaW0gfHwgZS5hbmltID09IGFuaW0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhbmltKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZS5zdGF0dXM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbTogZS5hbmltLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiBlLnN0YXR1c1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYW5pbSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucGF1c2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFN0b3BzIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudCB3aXRoIGFiaWxpdHkgdG8gcmVzdW1lIGl0IGxhdGVyIG9uLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBhbmltIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0XG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnBhdXNlID0gZnVuY3Rpb24gKGFuaW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkrKykgaWYgKGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsLmlkID09IHRoaXMuaWQgJiYgKCFhbmltIHx8IGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0gPT0gYW5pbSk
57590pIHtcbiAgICAgICAgICAgIGlmIChldmUoXCJyYXBoYWVsLmFuaW0ucGF1c2UuXCIgKyB0aGlzLmlkLCB0aGlzLCBhbmltYXRpb25FbGVtZW50c1tpXS5hbmltKSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25FbGVtZW50c1tpXS5wYXVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQucmVzdW1lXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXN1bWVzIGFuaW1hdGlvbiBpZiBpdCB3YXMgcGF1c2VkIHdpdGggQEVsZW1lbnQucGF1c2UgbWV0aG9kLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBhbmltIChvYmplY3QpICNvcHRpb25hbCBhbmltYXRpb24gb2JqZWN0XG4gICAgICoqXG4gICAgID0gKG9iamVjdCkgb3JpZ2luYWwgZWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJlc3VtZSA9IGZ1bmN0aW9uIChhbmltKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYW5pbWF0aW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIGlmIChhbmltYXRpb25FbGVtZW50c1tpXS5lbC5pZCA9PSB0aGlzLmlkICYmICghYW5pbSB8fCBhbmltYXRpb25FbGVtZW50c1tpXS5hbmltID09IGFuaW0pKSB7XG4gICAgICAgICAgICB2YXIgZSA9IGFuaW1hdGlvbkVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKGV2ZShcInJhcGhhZWwuYW5pbS5yZXN1bWUuXCIgKyB0aGlzLmlkLCB0aGlzLCBlLmFuaW0pICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBlLnBhdXNlZDtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXR1cyhlLmFuaW0sIGUuc3RhdHVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnN0b3BcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFN0b3BzIGFuaW1hdGlvbiBvZiB0aGUgZWxlbWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gYW5pbSAob2JqZWN0KSAjb3B0aW9uYWwgYW5pbWF0aW9uIG9iamVjdFxuICAgICAqKlxuICAgICA9IChvYmplY3QpIG9yaWdpbmFsIGVsZW1lbnRcbiAgICBcXCovXG4gICAgZWxwcm90by5zdG9wID0gZnVuY3Rpb24gKGFuaW0pIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbmltYXRpb25FbGVtZW50cy5sZW5ndGg7IGkrKykgaWYgKGFuaW1hdGlvbkVsZW1lbnRzW2ldLmVsLmlkID09IHRoaXMuaWQgJiYgKCFhbmltIHx8IGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0gPT0gYW5pbSkpIHtcbiAgICAgICAgICAgIGlmIChldmUoXCJyYXBoYWVsLmFuaW0uc3RvcC5cIiArIHRoaXMuaWQsIHRoaXMsIGFuaW1hdGlvbkVsZW1lbnRzW2ldLmFuaW0pICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShpLS0sIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZnVuY3Rpb24gc3RvcEFuaW1hdGlvbihwYXBlcikge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFuaW1hdGlvbkVsZW1lbnRzLmxlbmd0aDsgaSsrKSBpZiAoYW5pbWF0aW9uRWxlbWVudHNbaV0uZWwucGFwZXIgPT0gcGFwZXIpIHtcbiAgICAgICAgICAgIGFuaW1hdGlvbkVsZW1lbnRzLnNwbGljZShpLS0sIDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGV2ZS5vbihcInJhcGhhZWwucmVtb3ZlXCIsIHN0b3BBbmltYXRpb24pO1xuICAgIGV2ZS5vbihcInJhcGhhZWwuY2xlYXJcIiwgc3RvcEFuaW1hdGlvbik7XG4gICAgZWxwcm90by50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmFwaGFcXHhlYmxcXHUyMDE5cyBvYmplY3RcIjtcbiAgICB9O1xuXG4gICAgLy8gU2V0XG4gICAgdmFyIFNldCA9IGZ1bmN0aW9uIChpdGVtcykge1xuICAgICAgICB0aGlzLml0ZW1zID0gW107XG4gICAgICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy50eXBlID0gXCJzZXRcIjtcbiAgICAgICAgaWYgKGl0ZW1zKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBpdGVtcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW1zW2ldICYmIChpdGVtc1tpXS5jb25zdHJ1Y3RvciA9PSBlbHByb3RvLmNvbnN0cnVjdG9yIHx8IGl0ZW1zW2ldLmNvbnN0cnVjdG9yID09IFNldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1t0aGlzLml0ZW1zLmxlbmd0aF0gPSB0aGlzLml0ZW1zW3RoaXMuaXRlbXMubGVuZ3RoXSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG4gICAgc2V0cHJvdG8gPSBTZXQucHJvdG90eXBlO1xuICAgIC8qXFxcbiAgICAgKiBTZXQucHVzaFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQWRkcyBlYWNoIGFyZ3VtZW50IHRvIHRoZSBjdXJyZW50IHNldC5cbiAgICAgPSAob2JqZWN0KSBvcmlnaW5hbCBlbGVtZW50XG4gICAgXFwqL1xuICAgIHNldHByb3RvLnB1c2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpdGVtLFxuICAgICAgICAgICAgbGVuO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgaXRlbSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGlmIChpdGVtICYmIChpdGVtLmNvbnN0cnVjdG9yID09IGVscHJvdG8uY29uc3RydWN0b3IgfHwgaXRlbS5jb25zdHJ1Y3RvciA9PSBTZXQpKSB7XG4gICAgICAgICAgICAgICAgbGVuID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdGhpc1tsZW5dID0gdGhpcy5pdGVtc1tsZW5dID0gaXRlbTtcbiAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgI
57590HJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFNldC5wb3BcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgbGFzdCBlbGVtZW50IGFuZCByZXR1cm5zIGl0LlxuICAgICA9IChvYmplY3QpIGVsZW1lbnRcbiAgICBcXCovXG4gICAgc2V0cHJvdG8ucG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmxlbmd0aCAmJiBkZWxldGUgdGhpc1t0aGlzLmxlbmd0aC0tXTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMucG9wKCk7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogU2V0LmZvckVhY2hcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEV4ZWN1dGVzIGdpdmVuIGZ1bmN0aW9uIGZvciBlYWNoIGVsZW1lbnQgaW4gdGhlIHNldC5cbiAgICAgKlxuICAgICAqIElmIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYCBpdCB3aWxsIHN0b3AgbG9vcCBydW5uaW5nLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBjYWxsYmFjayAoZnVuY3Rpb24pIGZ1bmN0aW9uIHRvIHJ1blxuICAgICAtIHRoaXNBcmcgKG9iamVjdCkgY29udGV4dCBvYmplY3QgZm9yIHRoZSBjYWxsYmFja1xuICAgICA9IChvYmplY3QpIFNldCBvYmplY3RcbiAgICBcXCovXG4gICAgc2V0cHJvdG8uZm9yRWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLml0ZW1zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjay5jYWxsKHRoaXNBcmcsIHRoaXMuaXRlbXNbaV0sIGkpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSkge1xuICAgICAgICBzZXRwcm90b1ttZXRob2RdID0gKGZ1bmN0aW9uIChtZXRob2RuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxbbWV0aG9kbmFtZV1bYXBwbHldKGVsLCBhcmcpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSkobWV0aG9kKTtcbiAgICB9XG4gICAgc2V0cHJvdG8uYXR0ciA9IGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSkge1xuICAgICAgICBpZiAobmFtZSAmJiBSLmlzKG5hbWUsIGFycmF5KSAmJiBSLmlzKG5hbWVbMF0sIFwib2JqZWN0XCIpKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBuYW1lLmxlbmd0aDsgaiA8IGpqOyBqKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW2pdLmF0dHIobmFtZVtqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLml0ZW1zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1zW2ldLmF0dHIobmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFNldC5jbGVhclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBhbGwgZWxlbWVudHMgZnJvbSB0aGUgc2V0XG4gICAgXFwqL1xuICAgIHNldHByb3RvLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB3aGlsZSAodGhpcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMucG9wKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBTZXQuc3BsaWNlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZW1vdmVzIGdpdmVuIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG4gICAgICoqXG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAqKlxuICAgICAtIGluZGV4IChudW1iZXIpIHBvc2l0aW9uIG9mIHRoZSBkZWxldGlvblxuICAgICAtIGNvdW50IChudW1iZXIpIG51bWJlciBvZiBlbGVtZW50IHRvIHJlbW92ZVxuICAgICAtIGluc2VydGlvbuKApiAob2JqZWN0KSAjb3B0aW9uYWwgZWxlbWVudHMgdG8gaW5zZXJ0XG4gICAgID0gKG9iamVjdCkgc2V0IGVsZW1lbnRzIHRoYXQgd2VyZSBkZWxldGVkXG4gICAgXFwqL1xuICAgIHNldHByb3RvLnNwbGljZSA9IGZ1bmN0aW9uIChpbmRleCwgY291bnQsIGluc2VydGlvbikge1xuICAgICAgICBpbmRleCA9IGluZGV4IDwgMCA/IG1tYXgodGhpcy5sZW5ndGggKyBpbmRleCwgMCkgOiBpbmRleDtcbiAgICAgICAgY291bnQgPSBtbWF4KDAsIG1taW4odGhpcy5sZW5ndGggLSBpbmRleCwgY291bnQpKTtcbiAgICAgICAgdmFyIHRhaWwgPSBbXSxcbiAgICAgICAgICAgIHRvZGVsID0gW10sXG4gICAgICAgICAgICBhcmdzID0gW10sXG4gICAgICAgICAgICBpO1xuICAgICAgICBmb3IgKGkgPSAyOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgdG9kZWwucHVzaCh0aGlzW2luZGV4ICsgaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBpIDwgdGhpcy5sZW5ndGggLSBpbmRleDsgaSsrKSB7XG4gICAgICAgICAgICB0YWlsLnB1c2godGhpc1tpbmRleCArIGldKTtcbiAgICAgICAgfVxuICAgICAgICB2Y
57590XIgYXJnbGVuID0gYXJncy5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBhcmdsZW4gKyB0YWlsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLml0ZW1zW2luZGV4ICsgaV0gPSB0aGlzW2luZGV4ICsgaV0gPSBpIDwgYXJnbGVuID8gYXJnc1tpXSA6IHRhaWxbaSAtIGFyZ2xlbl07XG4gICAgICAgIH1cbiAgICAgICAgaSA9IHRoaXMuaXRlbXMubGVuZ3RoID0gdGhpcy5sZW5ndGggLT0gY291bnQgLSBhcmdsZW47XG4gICAgICAgIHdoaWxlICh0aGlzW2ldKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpc1tpKytdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2V0KHRvZGVsKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBTZXQuZXhjbHVkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBnaXZlbiBlbGVtZW50IGZyb20gdGhlIHNldFxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBlbGVtZW50IChvYmplY3QpIGVsZW1lbnQgdG8gcmVtb3ZlXG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBvYmplY3Qgd2FzIGZvdW5kICYgcmVtb3ZlZCBmcm9tIHRoZSBzZXRcbiAgICBcXCovXG4gICAgc2V0cHJvdG8uZXhjbHVkZSA9IGZ1bmN0aW9uIChlbCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLmxlbmd0aDsgaSA8IGlpOyBpKyspIGlmICh0aGlzW2ldID09IGVsKSB7XG4gICAgICAgICAgICB0aGlzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBzZXRwcm90by5hbmltYXRlID0gZnVuY3Rpb24gKHBhcmFtcywgbXMsIGVhc2luZywgY2FsbGJhY2spIHtcbiAgICAgICAgKFIuaXMoZWFzaW5nLCBcImZ1bmN0aW9uXCIpIHx8ICFlYXNpbmcpICYmIChjYWxsYmFjayA9IGVhc2luZyB8fCBudWxsKTtcbiAgICAgICAgdmFyIGxlbiA9IHRoaXMuaXRlbXMubGVuZ3RoLFxuICAgICAgICAgICAgaSA9IGxlbixcbiAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICBzZXQgP
57590SB0aGlzLFxuICAgICAgICAgICAgY29sbGVjdG9yO1xuICAgICAgICBpZiAoIWxlbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgY2FsbGJhY2sgJiYgKGNvbGxlY3RvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICEtLWxlbiAmJiBjYWxsYmFjay5jYWxsKHNldCk7XG4gICAgICAgIH0pO1xuICAgICAgICBlYXNpbmcgPSBSLmlzKGVhc2luZywgc3RyaW5nKSA/IGVhc2luZyA6IGNvbGxlY3RvcjtcbiAgICAgICAgdmFyIGFuaW0gPSBSLmFuaW1hdGlvbihwYXJhbXMsIG1zLCBlYXNpbmcsIGNvbGxlY3Rvcik7XG4gICAgICAgIGl0ZW0gPSB0aGlzLml0ZW1zWy0taV0uYW5pbWF0ZShhbmltKTtcbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgdGhpcy5pdGVtc1tpXSAmJiAhdGhpcy5pdGVtc1tpXS5yZW1vdmVkICYmIHRoaXMuaXRlbXNbaV0uYW5pbWF0ZVdpdGgoaXRlbSwgYW5pbSwgYW5pbSk7XG4gICAgICAgICAgICAodGhpcy5pdGVtc1tpXSAmJiAhdGhpcy5pdGVtc1tpXS5yZW1vdmVkKSB8fCBsZW4tLTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIHNldHByb3RvLmluc2VydEFmdGVyID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBpID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHRoaXMuaXRlbXNbaV0uaW5zZXJ0QWZ0ZXIoZWwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgc2V0cHJvdG8uZ2V0QkJveCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHggPSBbXSxcbiAgICAgICAgICAgIHkgPSBbXSxcbiAgICAgICAgICAgIHgyID0gW10sXG4gICAgICAgICAgICB5MiA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gdGhpcy5pdGVtcy5sZW5ndGg7IGktLTspIGlmICghdGhpcy5pdGVtc1tpXS5yZW1vdmVkKSB7XG4gICAgICAgICAgICB2Y
57590XIgYm94ID0gdGhpcy5pdGVtc1tpXS5nZXRCQm94KCk7XG4gICAgICAgICAgICB4LnB1c2goYm94LngpO1xuICAgICAgICAgICAgeS5wdXNoKGJveC55KTtcbiAgICAgICAgICAgIHgyLnB1c2goYm94LnggKyBib3gud2lkdGgpO1xuICAgICAgICAgICAgeTIucHVzaChib3gueSArIGJveC5oZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHggPSBtbWluW2FwcGx5XSgwLCB4KTtcbiAgICAgICAgeSA9IG1taW5bYXBwbHldKDAsIHkpO1xuICAgICAgICB4MiA9IG1tYXhbYXBwbHldKDAsIHgyKTtcbiAgICAgICAgeTIgPSBtbWF4W2FwcGx5XSgwLCB5Mik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgIHgyOiB4MixcbiAgICAgICAgICAgIHkyOiB5MixcbiAgICAgICAgICAgIHdpZHRoOiB4MiAtIHgsXG4gICAgICAgICAgICBoZWlnaHQ6IHkyIC0geVxuICAgICAgICB9O1xuICAgIH07XG4gICAgc2V0cHJvdG8uY2xvbmUgPSBmdW5jdGlvbiAocykge1xuICAgICAgICBzID0gdGhpcy5wYXBlci5zZXQoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGhpcy5pdGVtcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBzLnB1c2godGhpcy5pdGVtc1tpXS5jbG9uZSgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcztcbiAgICB9O1xuICAgIHNldHByb3RvLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSYXBoYVxceGVibFxcdTIwMThzIHNldFwiO1xuICAgIH07XG5cbiAgICBzZXRwcm90by5nbG93ID0gZnVuY3Rpb24oZ2xvd0NvbmZpZykge1xuICAgICAgICB2Y
57590XIgcmV0ID0gdGhpcy5wYXBlci5zZXQoKTtcbiAgICAgICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHNoYXBlLCBpbmRleCl7XG4gICAgICAgICAgICB2YXIgZyA9IHNoYXBlLmdsb3coZ2xvd0NvbmZpZyk7XG4gICAgICAgICAgICBpZihnICE9IG51bGwpe1xuICAgICAgICAgICAgICAgIGcuZm9yRWFjaChmdW5jdGlvbihzaGFwZTIsIGluZGV4Mil7XG4gICAgICAgICAgICAgICAgICAgIHJldC5wdXNoKHNoYXBlMik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH07XG5cblxuICAgIC8qXFxcbiAgICAgKiBTZXQuaXNQb2ludEluc2lkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRGV0ZXJtaW5lIGlmIGdpdmVuIHBvaW50IGlzIGluc2lkZSB0aGlzIHNldOKAmXMgZWxlbWVudHNcbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0geCAobnVtYmVyKSB4IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgIC0geSAobnVtYmVyKSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCBpZiBwb2ludCBpcyBpbnNpZGUgYW55IG9mIHRoZSBzZXQncyBlbGVtZW50c1xuICAgICBcXCovXG4gICAgc2V0cHJvdG8uaXNQb2ludEluc2lkZSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIHZhciBpc1BvaW50SW5zaWRlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgICAgIGlmIChlbC5pc1BvaW50SW5zaWRlKHgsIHkpKSB7XG4gICAgICAgICAgICAgICAgaXNQb2ludEluc2lkZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzdG9wIGxvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBpc1BvaW50SW5zaWRlO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5yZWdpc3RlckZvbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgZ2l2ZW4gZm9udCB0byB0aGUgcmVnaXN0ZXJlZCBzZXQgb2YgZm9udHMgZm9yIFJhcGhhw6tsLiBTaG91bGQgYmUgdXNlZCBhcyBhbiBpbnRlcm5hbCBjYWxsIGZyb20gd2l0aGluIEN1ZsOzbuKAmXMgZm9udCBmaWxlLlxuICAgICAqIFJldHVybnMgb3JpZ2luYWwgcGFyYW1ldGVyLCBzbyBpdCBjb3VsZCBiZSB1c2VkIHdpdGggY2hhaW5pbmcuXG4gICAgICMgPGEgaHJlZj1cImh0dHA6Ly93aWtpLmdpdGh1Yi5jb20vc29yY2N1L2N1Zm9uL2Fib3V0XCI+TW9yZSBhYm91dCBDdWbDs24gYW5kIGhvdyB0byBjb252ZXJ0IHlvdXIgZm9udCBmb3JtIFRURiwgT1RGLCBldGMgdG8gSmF2YVNjcmlwdCBmaWxlLjwvYT5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gZm9udCAob2JqZWN0KSB0aGUgZm9udCB0byByZWdpc3RlclxuICAgICA9IChvYmplY3QpIHRoZSBmb250IHlvdSBwYXNzZWQgaW5cbiAgICAgPiBVc2FnZVxuICAgICB8IEN1Zm9uLnJlZ2lzdGVyRm9udChSYXBoYWVsLnJlZ2lzdGVyRm9udCh74oCmfSkpO1xuICAgIFxcKi9cbiAgICBSLnJlZ2lzdGVyRm9udCA9IGZ1bmN0aW9uIChmb250KSB7XG4gICAgICAgIGlmICghZm9udC5mYWNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9udDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvbnRzID0gdGhpcy5mb250cyB8fCB7fTtcbiAgICAgICAgdmFyIGZvbnRjb3B5ID0ge1xuICAgICAgICAgICAgICAgIHc6IGZvbnQudyxcbiAgICAgICAgICAgICAgICBmYWNlOiB7fSxcbiAgICAgICAgICAgICAgICBnbHlwaHM6IHt9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmFtaWx5ID0gZm9udC5mYWNlW1wiZm9udC1mYW1pbHlcIl07XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gZm9udC5mYWNlKSBpZiAoZm9udC5mYWNlW2hhc10ocHJvcCkpIHtcbiAgICAgICAgICAgIGZvbnRjb3B5LmZhY2VbcHJvcF0gPSBmb250LmZhY2VbcHJvcF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZm9udHNbZmFtaWx5XSkge1xuICAgICAgICAgICAgdGhpcy5mb250c1tmYW1pbHldLnB1c2goZm9udGNvcHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mb250c1tmYW1pbHldID0gW2ZvbnRjb3B5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZvbnQuc3ZnKSB7XG4gICAgICAgICAgICBmb250Y29weS5mYWNlW1widW5pdHMtcGVyLWVtXCJdID0gdG9JbnQoZm9udC5mYWNlW1widW5pdHMtcGVyLWVtXCJdLCAxMCk7XG4gICAgICAgICAgICBmb3IgKHZhciBnbHlwaCBpbiBmb250LmdseXBocykgaWYgKGZvbnQuZ2x5cGhzW2hhc10oZ2x5cGgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGggPSBmb250LmdseXBoc1tnbHlwaF07XG4gICAgICAgICAgICAgICAgZm9udGNvcHkuZ2x5cGhzW2dseXBoXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgdzogcGF0aC53LFxuICAgICAgICAgICAgICAgICAgICBrOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgZDogcGF0aC5kICYmIFwiTVwiICsgcGF0aC5kLnJlcGxhY2UoL1ttbGN4dHJ2XS9nLCBmdW5jdGlvbiAoY29tbWFuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7bDogXCJMXCIsIGM6IFwiQ1wiLCB4OiBcInpcIiwgdDogXCJtXCIsIHI6IFwibFwiLCB2OiBcImNcIn1bY29tbWFuZF0gfHwgXCJNXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSArIFwielwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAocGF0aC5rKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcGF0aC5rKSBpZiAocGF0aFtoYXNdKGspKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb250Y29weS5nbHlwaHNbZ2x5cGhdLmtba10gPSBwYXRoLmtba107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvbnQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUGFwZXIuZ2V0Rm9udFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRmluZHMgZm9udCBvYmplY3QgaW4gdGhlIHJlZ2lzdGVyZWQgZm9udHMgYnkgZ2l2ZW4gcGFyYW1ldGVycy4gWW91IGNvdWxkIHNwZWNpZnkgb25seSBvbmUgd29yZCBmcm9tIHRoZSBmb250IG5hbW
57590UsIGxpa2Ug4oCcTXlyaWFk4oCdIGZvciDigJxNeXJpYWQgUHJv4oCdLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBmYW1pbHkgKHN0cmluZykgZm9udCBmYW1pbHkgbmFtZSBvciBhbnkgd29yZCBmcm9tIGl0XG4gICAgIC0gd2VpZ2h0IChzdHJpbmcpICNvcHRpb25hbCBmb250IHdlaWdodFxuICAgICAtIHN0eWxlIChzdHJpbmcpICNvcHRpb25hbCBmb250IHN0eWxlXG4gICAgIC0gc3RyZXRjaCAoc3RyaW5nKSAjb3B0aW9uYWwgZm9udCBzdHJldGNoXG4gICAgID0gKG9iamVjdCkgdGhlIGZvbnQgb2JqZWN0XG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5wcmludCgxMDAsIDEwMCwgXCJUZXN0IHN0cmluZ1wiLCBwYXBlci5nZXRGb250KFwiVGltZXNcIiwgODAwKSwgMzApO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmdldEZvbnQgPSBmdW5jdGlvbiAoZmFtaWx5LCB3ZWlnaHQsIHN0eWxlLCBzdHJldGNoKSB7XG4gICAgICAgIHN0cmV0Y2ggPSBzdHJldGNoIHx8IFwibm9ybWFsXCI7XG4gICAgICAgIHN0eWxlID0gc3R5bGUgfHwgXCJub3JtYWxcIjtcbiAgICAgICAgd2VpZ2h0ID0gK3dlaWdodCB8fCB7bm9ybWFsOiA0MDAsIGJvbGQ6IDcwMCwgbGlnaHRlcjogMzAwLCBib2xkZXI6IDgwMH1bd2VpZ2h0XSB8fCA0MDA7XG4gICAgICAgIGlmICghUi5mb250cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmb250ID0gUi5mb250c1tmYW1pbHldO1xuICAgICAgICBpZiAoIWZvbnQpIHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgZmFtaWx5LnJlcGxhY2UoL1teXFx3XFxkXFxzKyF+LjpfLV0vZywgRSkgKyBcIihcXFxcc3wkKVwiLCBcImlcIik7XG4gICAgICAgICAgICBmb3IgKHZhciBmb250TmFtZSBpbiBSLmZvbnRzKSBpZiAoUi5mb250c1toYXNdKGZvbnROYW1lKSkge1xuICAgICAgICAgICAgICAgIGlmIChuYW1lLnRlc3QoZm9udE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvbnQgPSBSLmZvbnRzW2ZvbnROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB0aGVmb250O1xuICAgICAgICBpZiAoZm9udCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZm9udC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhlZm9udCA9IGZvbnRbaV07XG4gICAgICAgICAgICAgICAgaWYgKHRoZWZvbnQuZmFjZVtcImZvbnQtd2VpZ2h0XCJdID09IHdlaWdodCAmJiAodGhlZm9udC5mYWNlW1wiZm9udC1zdHlsZVwiXSA9PSBzdHlsZSB8fCAhdGhlZm9udC5mYWNlW1wiZm9udC1zdHlsZVwiXSkgJiYgdGhlZm9udC5mYWNlW1wiZm9udC1zdHJldGNoXCJdID09IHN0cmV0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGVmb250O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnByaW50XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBDcmVhdGVzIHBhdGggdGhhdCByZXByZXNlbnQgZ2l2ZW4gdGV4dCB3cml0dGVuIHVzaW5nIGdpdmVuIGZvbnQgYXQgZ2l2ZW4gcG9zaXRpb24gd2l0aCBnaXZlbiBzaXplLlxuICAgICAqIFJlc3VsdCBvZiB0aGUgbWV0aG9kIGlzIHBhdGggZWxlbWVudCB0aGF0IGNvbnRhaW5zIHdob2xlIHRleHQgYXMgYSBzZXBhcmF0ZSBwYXRoLlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB4IChudW1iZXIpIHggcG9zaXRpb24gb2YgdGhlIHRleHRcbiAgICAgLSB5IChudW1iZXIpIHkgcG9zaXRpb24gb2YgdGhlIHRleHRcbiAgICAgLSBzdHJpbmcgKHN0cmluZykgdGV4dCB0byBwcmludFxuICAgICAtIGZvbnQgKG9iamVjdCkgZm9udCBvYmplY3QsIHNlZSBAUGFwZXIuZ2V0Rm9udFxuICAgICAtIHNpemUgKG51bWJlcikgI29wdGlvbmFsIHNpemUgb2YgdGhlIGZvbnQsIGRlZmF1bHQgaXMgYDE2YFxuICAgICAtIG9yaWdpbiAoc3RyaW5nKSAjb3B0aW9uYWwgY291bGQgYmUgYFwiYmFzZWxpbmVcImAgb3IgYFwibWlkZGxlXCJgLCBkZWZhdWx0IGlzIGBcIm1pZGRsZVwiYFxuICAgICAtIGxldHRlcl9zcGFjaW5nIChudW1iZXIpICNvcHRpb25hbCBudW1iZXIgaW4gcmFuZ2UgYC0xLi4xYCwgZGVmYXVsdCBpcyBgMGBcbiAgICAgLSBsaW5lX3NwYWNpbmcgKG51bWJlcikgI29wdGlvbmFsIG51bWJlciBpbiByYW5nZSBgMS4uM2AsIGRlZmF1bHQgaXMgYDFgXG4gICAgID0gKG9iamVjdCkgcmVzdWx0aW5nIHBhdGggZWxlbWVudCwgd2hpY2ggY29uc2lzdCBvZiBhbGwgbGV0dGVyc1xuICAgICA+IFVzYWdlXG4gICAgIHwgdmFyIHR4dCA9IHIucHJpbnQoMTAsIDUwLCBcInByaW50XCIsIHIuZ2V0Rm9udChcIk11c2VvXCIpLCAzMCkuYXR0cih7ZmlsbDogXCIjZmZmXCJ9KTtcbiAgICBcXCovXG4gICAgcGFwZXJwcm90by5wcmludCA9IGZ1bmN0aW9uICh4LCB5LCBzdHJpbmcsIGZvbnQsIHNpemUsIG9yaWdpbiwgbGV0dGVyX3NwYWNpbmcsIGxpbmVfc3BhY2luZykge1xuICAgICAgICBvcmlnaW4gPSBvcmlnaW4gfHwgXCJtaWRkbGVcIjsgLy8gYmFzZWxpbmV8bWlkZGxlXG4gICAgICAgIGxldHRlcl9zcGFjaW5nID0gbW1heChtbWluKGxldHRlcl9zcGFjaW5nIHx8IDAsIDEpLCAtMSk7XG4gICAgICAgIGxpbmVfc3BhY2luZyA9IG1tYXgobW1pbihsaW5lX3NwYWNpbmcgfHwgMSwgMyksIDEpO1xuICAgICAgICB2Y
57590XIgbGV0dGVycyA9IFN0cihzdHJpbmcpW3NwbGl0XShFKSxcbiAgICAgICAgICAgIHNoaWZ0ID0gMCxcbiAgICAgICAgICAgIG5vdGZpcnN0ID0gMCxcbiAgICAgICAgICAgIHBhdGggPSBFLFxuICAgICAgICAgICAgc2NhbGU7XG4gICAgICAgIFIuaXMoZm9udCwgXCJzdHJpbmdcIikgJiYgKGZvbnQgPSB0aGlzLmdldEZvbnQoZm9udCkpO1xuICAgICAgICBpZiAoZm9udCkge1xuICAgICAgICAgICAgc2NhbGUgPSAoc2l6ZSB8fCAxNikgLyBmb250LmZhY2VbXCJ1bml0cy1wZXItZW1cIl07XG4gICAgICAgICAgICB2YXIgYmIgPSBmb250LmZhY2UuYmJveFtzcGxpdF0oc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICB0b3AgPSArYmJbMF0sXG4gICAgICAgICAgICAgICAgbGluZUhlaWdodCA9IGJiWzNdIC0gYmJbMV0sXG4gICAgICAgICAgICAgICAgc2hpZnR5ID0gMCxcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSArYmJbMV0gKyAob3JpZ2luID09IFwiYmFzZWxpbmVcIiA/IGxpbmVIZWlnaHQgKyAoK2ZvbnQuZmFjZS5kZXNjZW50KSA6IGxpbmVIZWlnaHQgLyAyKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGxldHRlcnMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChsZXR0ZXJzW2ldID09IFwiXFxuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hpZnQgPSAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyID0gMDtcbiAgICAgICAgICAgICAgICAgICAgbm90Zmlyc3QgPSAwO1xuICAgICAgICAgICAgICAgICAgICBzaGlmdHkgKz0gbGluZUhlaWdodCAqIGxpbmVfc3BhY2luZztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2Y
57590XIgcHJldiA9IG5vdGZpcnN0ICYmIGZvbnQuZ2x5cGhzW2xldHRlcnNbaSAtIDFdXSB8fCB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnIgPSBmb250LmdseXBoc1tsZXR0ZXJzW2ldXTtcbiAgICAgICAgICAgICAgICAgICAgc2hpZnQgKz0gbm90Zmlyc3QgPyAocHJldi53IHx8IGZvbnQudykgKyAocHJldi5rICYmIHByZXYua1tsZXR0ZXJzW2ldXSB8fCAwKSArIChmb250LncgKiBsZXR0ZXJfc3BhY2luZykgOiAwO1xuICAgICAgICAgICAgICAgICAgICBub3RmaXJzdCA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyICYmIGN1cnIuZCkge1xuICAgICAgICAgICAgICAgICAgICBwYXRoICs9IFIudHJhbnNmb3JtUGF0aChjdXJyLmQsIFtcInRcIiwgc2hpZnQgKiBzY2FsZSwgc2hpZnR5ICogc2NhbGUsIFwic1wiLCBzY2FsZSwgc2NhbGUsIHRvcCwgaGVpZ2h0LCBcInRcIiwgKHggLSB0b3ApIC8gc2NhbGUsICh5IC0gaGVpZ2h0KSAvIHNjYWxlXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnBhdGgocGF0aCkuYXR0cih7XG4gICAgICAgICAgICBmaWxsOiBcIiMwMDBcIixcbiAgICAgICAgICAgIHN0cm9rZTogXCJub25lXCJcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qXFxcbiAgICAgKiBQYXBlci5hZGRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEltcG9ydHMgZWxlbWVudHMgaW4gSlNPTiBhcnJheSBpbiBmb3JtYXQgYHt0eXBlOiB0eXBlLCA8YXR0cmlidXRlcz59YFxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSBqc29uIChhcnJheSlcbiAgICAgPSAob2JqZWN0KSByZXN1bHRpbmcgc2V0IG9mIGltcG9ydGVkIGVsZW1lbnRzXG4gICAgID4gVXNhZ2VcbiAgICAgfCBwYXBlci5hZGQoW1xuICAgICB8ICAgICB7XG4gICAgIHwgICAgICAgICB0eXBlOiBcImNpcmNsZVwiLFxuICAgICB8ICAgICAgICAgY3g6IDEwLFxuICAgICB8ICAgICAgICAgY3k6IDEwLFxuICAgICB8ICAgICAgICAgcjogNVxuICAgICB8ICAgICB9LFxuICAgICB8ICAgICB7XG4gICAgIHwgICAgICAgICB0eXBlOiBcInJlY3RcIixcbiAgICAgfCAgICAgICAgIHg6IDEwLFxuICAgICB8ICAgICAgICAgeTogMTAsXG4gICAgIHwgICAgICAgICB3aWR0aDogMTAsXG4gICAgIHwgICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICB8ICAgICAgICAgZmlsbDogXCIjZmMwXCJcbiAgICAgfCAgICAgfVxuICAgICB8IF0pO1xuICAgIFxcKi9cbiAgICBwYXBlcnByb3RvLmFkZCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIGlmIChSLmlzKGpzb24sIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSB0aGlzLnNldCgpLFxuICAgICAgICAgICAgICAgIGkgPSAwLFxuICAgICAgICAgICAgICAgIGlpID0ganNvbi5sZW5ndGgsXG4gICAgICAgICAgICAgICAgajtcbiAgICAgICAgICAgIGZvciAoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGogPSBqc29uW2ldIHx8IHt9O1xuICAgICAgICAgICAgICAgIGVsZW1lbnRzW2hhc10oai50eXBlKSAmJiByZXMucHVzaCh0aGlzW2oudHlwZV0oKS5hdHRyKGopKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG5cbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mb3JtYXRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFNpbXBsZSBmb3JtYXQgZnVuY3Rpb24uIFJlcGxhY2VzIGNvbnN0cnVjdGlvbiBvZiB0eXBlIOKAnGB7PG51bWJlcj59YOKAnSB0byB0aGUgY29ycmVzcG9uZGluZyBhcmd1bWVudC5cbiAgICAgKipcbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgICoqXG4gICAgIC0gdG9rZW4gKHN0cmluZykgc3RyaW5nIHRvIGZvcm1hdFxuICAgICAtIOKApiAoc3RyaW5nKSByZXN0IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHRyZWF0ZWQgYXMgcGFyYW1ldGVycyBmb3IgcmVwbGFjZW1lbnRcbiAgICAgPSAoc3RyaW5nKSBmb3JtYXRlZCBzdHJpbmdcbiAgICAgPiBVc2FnZVxuICAgICB8IHZhciB4ID0gMTAsXG4gICAgIHwgICAgIHkgPSAyMCxcbiAgICAgfCAgICAgd2lkdGggPSA0MCxcbiAgICAgfCAgICAgaGVpZ2h0ID0gNTA7XG4gICAgIHwgLy8gdGhpcyB3aWxsIGRyYXcgYSByZWN0YW5ndWxhciBzaGFwZSBlcXVpdmFsZW50IHRvIFwiTTEwLDIwaDQwdjUwaC00MHpcIlxuICAgICB8IHBhcGVyLnBhdGgoUmFwaGFlbC5mb3JtYXQoXCJNezB9LHsxfWh7Mn12ezN9aHs0fXpcIiwgeCwgeSwgd2lkdGgsIGhlaWdodCwgLXdpZHRoKSk7XG4gICAgXFwqL1xuICAgIFIuZm9ybWF0ID0gZnVuY3Rpb24gKHRva2VuLCBwYXJhbXMpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBSLmlzKHBhcmFtcywgYXJyYXkpID8gWzBdW2NvbmNhdF0ocGFyYW1zKSA6IGFyZ3VtZW50cztcbiAgICAgICAgdG9rZW4gJiYgUi5pcyh0b2tlbiwgc3RyaW5nKSAmJiBhcmdzLmxlbmd0aCAtIDEgJiYgKHRva2VuID0gdG9rZW4ucmVwbGFjZShmb3JtYXRyZywgZnVuY3Rpb24gKHN0ciwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3NbKytpXSA9PSBudWxsID8gRSA6IGFyZ3NbaV07XG4gICAgICAgIH0pKTtcbiAgICAgICAgcmV0dXJuIHRva2VuIHx8IEU7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogUmFwaGFlbC5mdWxsZmlsbFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQSBsaXR0bGUgYml0IG1vcmUgYWR2YW5jZWQgZm9ybWF0IGZ1bmN0aW9uIHRoYW4gQFJhcGhhZWwuZm9ybWF0LiBSZXBsYWNlcyBjb25zdHJ1Y3Rpb24gb2YgdHlwZSDigJxgezxuYW1lPn1g4oCdIHRvIHRoZSBjb3JyZXNwb25kaW5nIGFyZ3VtZW50LlxuICAgICAqKlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgKipcbiAgICAgLSB0b2tlbiAoc3RyaW5nKSBzdHJpbmcgdG8gZm9ybWF0XG4gICAgIC0ganNvbiAob2JqZWN0KSBvYmplY3Qgd2hpY2ggcHJvcGVydGllcyB3aWxsIGJlIHVzZWQgYXMgYSByZXBsYWNlbWVudFxuICAgICA9IChzdHJpbmcpIGZvcm1hdGVkIHN0cmluZ1xuICAgICA+IFVzYWdlXG4gICAgI
57590HwgLy8gdGhpcyB3aWxsIGRyYXcgYSByZWN0YW5ndWxhciBzaGFwZSBlcXVpdmFsZW50IHRvIFwiTTEwLDIwaDQwdjUwaC00MHpcIlxuICAgICB8IHBhcGVyLnBhdGgoUmFwaGFlbC5mdWxsZmlsbChcIk17eH0se3l9aHtkaW0ud2lkdGh9dntkaW0uaGVpZ2h0fWh7ZGltWyduZWdhdGl2ZSB3aWR0aCddfXpcIiwge1xuICAgICB8ICAgICB4OiAxMCxcbiAgICAgfCAgICAgeTogMjAsXG4gICAgIHwgICAgIGRpbToge1xuICAgICB8ICAgICAgICAgd2lkdGg6IDQwLFxuICAgICB8ICAgICAgICAgaGVpZ2h0OiA1MCxcbiAgICAgfCAgICAgICAgIFwibmVnYXRpdmUgd2lkdGhcIjogLTQwXG4gICAgIHwgICAgIH1cbiAgICAgfCB9KSk7XG4gICAgXFwqL1xuICAgIFIuZnVsbGZpbGwgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdG9rZW5SZWdleCA9IC9cXHsoW15cXH1dKylcXH0vZyxcbiAgICAgICAgICAgIG9iak5vdGF0aW9uUmVnZXggPSAvKD86KD86XnxcXC4pKC4rPykoPz1cXFt8XFwufCR8XFwoKXxcXFsoJ3xcIikoLis/KVxcMlxcXSkoXFwoXFwpKT8vZywgLy8gbWF0Y2hlcyAueHh4eHggb3IgW1wieHh4eHhcIl0gdG8gcnVuIG92ZXIgb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgICAgICAgIHJlcGxhY2VyID0gZnVuY3Rpb24gKGFsbCwga2V5LCBvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gb2JqO1xuICAgICAgICAgICAgICAgIGtleS5yZXBsYWNlKG9iak5vdGF0aW9uUmVnZXgsIGZ1bmN0aW9uIChhbGwsIG5hbWUsIHF1b3RlLCBxdW90ZWROYW1lLCBpc0Z1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZSA9IG5hbWUgfHwgcXVvdGVkTmFtZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgaW4gcmVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gcmVzW25hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHJlcyA9PSBcImZ1bmN0aW9uXCIgJiYgaXNGdW5jICYmIChyZXMgPSByZXMoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXMgPSAocmVzID09IG51bGwgfHwgcmVzID09IG9iaiA/IGFsbCA6IHJlcykgKyBcIlwiO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHN0ciwgb2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKHN0cikucmVwbGFjZSh0b2tlblJlZ2V4LCBmdW5jdGlvbiAoYWxsLCBrZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZXIoYWxsLCBrZXksIG9iaik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9KSgpO1xuICAgIC8qXFxcbiAgICAgKiBSYXBoYWVsLm5pbmphXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBsZWF2ZSBubyB0cmFjZSBvZiBSYXBoYcOrbCAoV2VsbCwgUmFwaGHDq2wgY3JlYXRlcyBvbmx5IG9uZSBnbG9iYWwgdmFyaWFibGUgYFJhcGhhZWxgLCBidXQgYW55d2F5LikgWW91IGNhbiB1c2UgYG5pbmphYCBtZXRob2QuXG4gICAgICogQmV3YXJlLCB0aGF0IGluIHRoaXMgY2FzZSBwbHVnaW5zIGNvdWxkIHN0b3Agd29ya2luZywgYmVjYXVzZSB0aGV5IGFyZSBkZXBlbmRpbmcgb24gZ2xvYmFsIHZhcmlhYmxlIGV4aXN0ZW5jZS5cbiAgICAgKipcbiAgICAgPSAob2JqZWN0KSBSYXBoYWVsIG9iamVjdFxuICAgICA+IFVzYWdlXG4gICAgIHwgKGZ1bmN0aW9uIChsb2NhbF9yYXBoYWVsKSB7XG4gICAgIHwgICAgIHZhciBwYXBlciA9IGxvY2FsX3JhcGhhZWwoMTAsIDEwLCAzMjAsIDIwMCk7XG4gICAgI
57590HwgICAgIOKAplxuICAgICB8IH0pKFJhcGhhZWwubmluamEoKSk7XG4gICAgXFwqL1xuICAgIFIubmluamEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChvbGRSYXBoYWVsLndhcykge1xuICAgICAgICAgICAgZy53aW4uUmFwaGFlbCA9IG9sZFJhcGhhZWwuaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJRTggcmFpc2VzIGFuIGVycm9yIHdoZW4gZGVsZXRpbmcgd2luZG93IHByb3BlcnR5XG4gICAgICAgICAgICB3aW5kb3cuUmFwaGFlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHdpbmRvdy5SYXBoYWVsO1xuICAgICAgICAgICAgfSBjYXRjaChlKSB7fVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFJhcGhhZWwuc3RcbiAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICoqXG4gICAgICogWW91IGNhbiBhZGQgeW91ciBvd24gbWV0aG9kIHRvIGVsZW1lbnRzIGFuZCBzZXRzLiBJdCBpcyB3aXNlIHRvIGFkZCBhIHNldCBtZXRob2QgZm9yIGVhY2ggZWxlbWVudCBtZXRob2RcbiAgICAgKiB5b3UgYWRkZWQsIHNvIHlvdSB3aWxsIGJlIGFibGUgdG8gY2FsbCB0aGUgc2FtZSBtZXRob2Qgb24gc2V0cyB0b28uXG4gICAgICoqXG4gICAgICogU2VlIGFsc28gQFJhcGhhZWwuZWwuXG4gICAgID4gVXNhZ2VcbiAgICAgfCBSYXBoYWVsLmVsLnJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgfCAgICAgdGhpcy5hdHRyKHtmaWxsOiBcIiNmMDBcIn0pO1xuICAgICB8IH07XG4gICAgIHwgUmFwaGFlbC5zdC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgIHwgICAgIHRoaXMuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcbiAgICAgfCAgICAgICAgIGVsLnJlZCgpO1xuICAgICB8ICAgICB9KTtcbiAgICAgfCB9O1xuICAgICB8IC8vIHRoZW4gdXNlIGl0XG4gICAgI
57590HwgcGFwZXIuc2V0KHBhcGVyLmNpcmNsZSgxMDAsIDEwMCwgMjApLCBwYXBlci5jaXJjbGUoMTEwLCAxMDAsIDIwKSkucmVkKCk7XG4gICAgXFwqL1xuICAgIFIuc3QgPSBzZXRwcm90bztcblxuICAgIGV2ZS5vbihcInJhcGhhZWwuRE9NbG9hZFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxvYWRlZCA9IHRydWU7XG4gICAgfSk7XG5cbiAgICAvLyBGaXJlZm94IDwzLjYgZml4OiBodHRwOi8vd2VicmVmbGVjdGlvbi5ibG9nc3BvdC5jb20vMjAwOS8xMS8xOTUtY2hhcnMtdG8taGVscC1sYXp5LWxvYWRpbmcuaHRtbFxuICAgIChmdW5jdGlvbiAoZG9jLCBsb2FkZWQsIGYpIHtcbiAgICAgICAgaWYgKGRvYy5yZWFkeVN0YXRlID09IG51bGwgJiYgZG9jLmFkZEV2ZW50TGlzdGVuZXIpe1xuICAgICAgICAgICAgZG9jLmFkZEV2ZW50TGlzdGVuZXIobG9hZGVkLCBmID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKGxvYWRlZCwgZiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGRvYy5yZWFkeVN0YXRlID0gXCJjb21wbGV0ZVwiO1xuICAgICAgICAgICAgfSwgZmFsc2UpO1xuICAgICAgICAgICAgZG9jLnJlYWR5U3RhdGUgPSBcImxvYWRpbmdcIjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc0xvYWRlZCgpIHtcbiAgICAgICAgICAgICgvaW4vKS50ZXN0KGRvYy5yZWFkeVN0YXRlKSA/IHNldFRpbWVvdXQoaXNMb2FkZWQsIDkpIDogUi5ldmUoXCJyYXBoYWVsLkRPTWxvYWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaXNMb2FkZWQoKTtcbiAgICB9KShkb2N1bWVudCwgXCJET01Db250ZW50TG9hZGVkXCIpO1xuXG4gICAgcmV0dXJuIFI7XG59KTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ
57590UNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO
575900FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./dev/raphael.core.js\n"); 57591 57592/***/ }), 57593
57594/***/ "./dev/raphael.svg.js": 57595/*!****************************!*\ 57596 !*** ./dev/raphael.svg.js ***! 57597 \****************************/ 57598/*! no static exports found */ 57599/***/ (function(module, exports, __webpack_require__) { 57600 57601eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n if (R && !R.svg) {\n return;\n }\n\n var has = \"hasOwnProperty\",\n Str = String,\n toFloat = parseFloat,\n toInt = parseInt,\n math = Math,\n mmax = math.max,\n abs = math.abs,\n pow = math.pow,\n separator = /[, ]+/,\n eve = R.eve,\n E = \"\",\n S = \" \";\n var xlink = \"http://www.w3.org/1999/xlink\",\n markers = {\n block: \"M5,0 0,2.5 5,5z\",\n classic: \"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",\n diamond: \"M2.5,0 5,2.5 2.5,5 0,2.5z\",\n open: \"M6,1 1,3.5 6,6\",\n oval: \"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"\n },\n markerCounter = {};\n R.toString = function () {\n return \"Your browser supports SVG.\\nYou are running Rapha\\xebl \" + this.version;\n };\n var $ = function (el, attr) {\n if (attr) {\n if (typeof el == \"string\") {\n el = $(el);\n }\n for (var key in attr) if (attr[has](key)) {\n if (key.substring(0, 6) == \"xlink:\") {\n el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));\n } else {\n el.setAttribute(key, Str(attr[key]));\n }\n }\n } else {\n el = R._g.doc.createElementNS(\"http://www.w3.org/2000/svg\", el);\n el.style && (el.style.webkitTapHighlightColor = \"rgba(0,0,0,0)\");\n }\n return el;\n },\n addGradientFill = function (element, gradient) {\n var type = \"linear\",\n id = element.id + gradient,\n fx = .5, fy = .5,\n o = element.node,\n SVG = element.paper,\n s = o.style,\n el = R._g.doc.getElementById(id);\n if (!el) {\n gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {\n type = \"radial\";\n if (_fx && _fy) {\n fx = toFloat(_fx);\n fy = toFloat(_fy);\n var dir = ((fy > .5) * 2 - 1);\n pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&\n (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&\n fy != .5 &&\n (fy = fy.toFixed(5) - 1e-5 * dir);\n }\n return E;\n });\n gradient = gradient.split(/\\s*\\-\\s*/);\n if (type == \"linear\") {\n var angle = gradient.shift();\n angle = -toFloat(angle);\n if (isNaN(angle)) {\n return null;\n }\n var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],\n max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);\n vector[2] *= max;\n vector[3] *= max;\n if (vector[2] < 0) {\n vector[0] = -vector[2];\n vector[2] = 0;\n }\n if (vector[3] < 0) {\n vector[1] = -vector[3];\n vector[3] = 0;\n }\n }\n var dots = R._parseDots(gradient);\n if (!dots) {\n return null;\n }\n id = id.replace(/[\\(\\)\\s,\\xb0#]/g, \"_\");\n\n if (element.gradient && id != element.gradient.id) {\n SVG.defs.removeChild(element.gradient);\n delete element.gradient;\n }\n\n if (!element.gradient) {\n el = $(type + \"Gradient\", {id: id});\n element.gradient = el;\n $(el, type == \"radial\" ? {\n fx: fx,\n fy: fy\n } : {\n x1: vector[0],\n y1: vector[1],\n x2: vector[2],\n y2: vector[3],\n gradientTransform: element.matrix.invert()\n });\n SVG.defs.appendChild(el);\n for (var i = 0, ii = dots.length; i < ii;
57601 i++) {\n el.appendChild($(\"stop\", {\n offset: dots[i].offset ? dots[i].offset : i ? \"100%\" : \"0%\",\n \"stop-color\": dots[i].color || \"#fff\",\n \"stop-opacity\": isFinite(dots[i].opacity) ? dots[i].opacity : 1\n }));\n }\n }\n }\n $(o, {\n fill: fillurl(id),\n opacity: 1,\n \"fill-opacity\": 1\n });\n s.fill = E;\n s.opacity = 1;\n s.fillOpacity = 1;\n return 1;\n },\n isIE9or10 = function () {\n var mode = document.documentMode;\n return mode && (mode === 9 || mode === 10);\n },\n fillurl = function (id) {\n if (isIE9or10()) {\n return \"url('#\" + id + \"')\";\n }\n var location = document.location;\n var locationString = (\n location.protocol + '//' +\n location.host +\n location.pathname +\n location.search\n );\n return \"url('\" + locationString + \"#\" + id + \"')\";\n },\n updatePosition = function (o) {\n var bbox = o.getBBox(1);\n $(o.pattern, {patternTransform: o.matrix.invert() + \" translate(\" + bbox.x + \",\" + bbox.y + \")\"});\n },\n addArrow = function (o, value, isEnd) {\n if (o.type == \"path\") {\n var values = Str(value).toLowerCase().split(\"-\"),\n p = o.paper,\n se = isEnd ? \"end\" : \"start\",\n node = o.node,\n attrs = o.attrs,\n stroke = attrs[\"stroke-width\"],\n i = values.length,\n type = \"classic\",\n from,\n to,\n dx,\n refX,\n attr,\n w = 3,\n h = 3,\n t = 5;\n while (i--) {\n switch (values[i]) {\n case \"block\":\n case \"classic\":\n case \"oval\":\n case \"diamond\":\n case \"open\":\n case \"none\":\n type = values[i];\n break;\n case \"wide\": h = 5; break;\n case \"narrow\": h = 2; break;\n case \"long\": w = 5; break;\n case \"short\": w = 2; break;\n }\n }\n if (type == \"open\") {\n w += 2;\n h += 2;\n t += 2;\n dx = 1;\n refX = isEnd ? 4 : 1;\n attr = {\n fill: \"none\",\n stroke: attrs.stroke\n };\n } else {\n refX = dx = w / 2;\n attr = {\n fill: attrs.stroke,\n stroke: \"none\"\n };\n }\n if (o._.arrows) {\n if (isEnd) {\n o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;\n o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;\n } else {\n o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;\n o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;\n }\n } else {\n o._.arrows = {};\n }\n if (type != \"none\") {\n var pathId = \"raphael-marker-\" + type,\n markerId = \"raphael-marker-\" + se + type + w + h + \"-obj\" + o.id;\n if (!R._g.doc.getElementById(pathId)) {\n p.defs.appendChild($($(\"path\"), {\n \"stroke-linecap\": \"round\",\n d: markers[type],\n id: pathId\n }));\n markerCounter[pathId] = 1;\n } else {\n markerCounter[pathId]++;\n }\n var marker = R._g.doc.getElementById(markerId),\n use;\n if (!marker) {\n marker = $($(\"marker\"), {\n id: markerId,\n markerHeight: h,\n markerWidth: w,\n orient: \"auto\",\n refX: refX,\n refY: h / 2\n });\n use = $($(\"use\"), {\n \"xlink:href\": \"#\" + pathId,\n transform: (isEnd ? \"rotate(180 \" + w / 2 + \" \" + h / 2 + \") \" : E) + \"scale(\" + w / t + \",\" + h / t + \")\",\n \"stroke-width\": (1 / ((w / t + h / t) / 2)).toFixed(4)\n });\n marker.appendChild(use);\n p.defs.appendChild(marker);\n markerCounter[markerId] = 1;\n } else {\n markerCounter[markerId]++;\n use = marker.getElementsByTagName(\"use\")[0];\n }\n $(use, attr);\n var delta = dx * (type != \"diamond\" && type != \"oval\");\n if (isEnd) {\n from = o._.arrows.startdx * stroke || 0;\n to = R.getTotalLength(attrs.path) - delta * stroke;\n } else {\n from = delta * stroke;\n to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n }\n attr = {};\n attr[\"marker-\" + se] = \"url(#\" + markerId + \")\";\n if (to || from) {\n attr.d = R.getSubpath(attrs.path, from, to);\n }\n $(node, attr);\n o._.arrows[se + \"Path\"] = pathId;\n o._.arrows[se + \"Marker\"] = markerId;\n o._.arrows[se + \"dx\"] = delta;\n o._.arrows[se + \"Type\"] = type;\n o._.arrows[se + \"String\"] = value;\n } else {\n if (isEnd) {\n from = o._.arrows.startdx * stroke || 0;\n to = R.getTotalLength(attrs.path) - from;\n } else {\n from = 0;\n to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);\n }\n o._.arrows[se + \"Path\"] && $(node, {d: R.getSubpath(attrs.path, from, to)});\n delete o._.arrows[se + \"Path\"];\n delete o._.arrows[se + \"Marker\"];\n delete o._.arrows[se + \"dx\"];\n delete o._.arrows[se + \"Type\"];\n delete o._.arrows[se + \"String\"];\n }\n for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {\n var item = R._g.doc.getElementById(attr);\n item && item.parentNode.removeChild(item);\n }\n }\n },\n dasharray = {\n \"-\": [3, 1],\n \".\": [1, 1],\n \"-.\": [3, 1, 1, 1],\n \"-..\": [3, 1, 1, 1, 1, 1],\n \". \": [1, 3],\n \"- \": [4, 3],\n \"--\": [8, 3],\n \"- .\": [4, 3, 1, 3],\n \"--.\": [8, 3, 1, 3],\n \"--..\": [8, 3, 1, 3, 1, 3]\n },\n addDashes = function (o, value, params) {\n value = dasharray[Str(value).toLowerCase()];\n if (value) {\n var width = o.attrs[\"stroke-width\"] || \"1\",\n butt = {round: width, square: width, butt: 0}[o.attrs[\"stroke-linecap\"] || params[\"stroke-linecap\"]] || 0,\n dashes = [],\n i = value.length;\n while (i--) {\n dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;\n }\n $(o.node, {\"stroke-dasharray\": dashes.join(\",\")});\n }\n else {\n $(o.node, {\"stroke-dasharray\": \"none\"});\n }\n },\n setFillAndStroke = function (o, params) {\n var node = o.node,\n attrs = o.attrs,\n vis = node.style.visibility;\n node.style.visibility = \"hidden\";\n for (var att in params) {\n if (params[has](att)) {\n if (!R._availableAttrs[has](att)) {\n continue;\n }\n var value = params[att];\n attrs[att] = value;\n switch (att) {\n case \"blur\":\n o.blur(value);\n break;\n case \"title\":\n var title = node.getElementsByTagName(\"title\");\n\n // Use the existing <title>.\n if (title.length && (title = title[0])) {\n title.firstChild.nodeValue = value;\n } else {\n title = $(\"title\");\n var val = R._g.doc.createTextNode(value);\n title.appendChild(val);\n node.appendChild(title);\n }\n break;\n case \"href\":\n case \"target\":\n var pn = node.parentNode;\n if (pn.tagName.toLowerCase() != \"a\") {\n var hl = $(\"a\");\n pn.insertBefore(hl, node);\n hl.appendChild(node);\n pn = hl;\n }\n if (att == \"target\") {\n pn.setAttributeNS(xlink, \"show\", value == \"blank\" ? \"new\" : value);\n } else {\n pn.setAttributeNS(xlink, att, value);\n }\n break;\n case \"cursor\":\n node.style.cursor = value;\n break;\n case \"transform\":\n o.transform(value);\n break;\n case \"arrow-start\":\n addArrow(o, value);\n break;\n case \"arrow-end\":\n addArrow(o, value, 1);\n break;\n case \"clip-rect\":\n var rect = Str(value).split(separator);\n if (rect.length == 4) {\n o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);\n var el = $(\"clipPath\"),\n rc = $(\"rect\");\n el.id = R.createUUID();\n $(rc, {\n x: rect[0],\n y: rect[1],\n width: rect[2],\n height: rect[3]\n });\n el.appendChild(rc);\n o.paper.defs.appendChild(el);\n $(node, {\"clip-path\": \"url(#\" + el.id + \")\"});\n o.clip = rc;\n }\n if (!value) {\n var path = node.getAttribute(\"clip-path\");\n if (path) {\n var clip = R._g.doc.getElementById(path.replace(/(^url\\(#|\\)$)/g, E));\n clip && clip.parentNode.removeChild(clip);\n $(node, {\"clip-path\": E});\n delete o.clip;\n }\n }\n break;\n case \"path\":\n if (o.type == \"path\") {\n $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : \"M0,0\"});\n o._.dirty = 1;\n if (o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n }\n break;\n case \"width\":\n node.setAttribute(att, value);\n o._.dirty = 1;\n if (attrs.fx) {\n att = \"x\";\n value = attrs.x;\n } else {\n break;\n }\n case \"x\":\n if (attrs.fx) {\n value = -attrs.x - (attrs.width || 0);\n }\n case \"rx\":\n if (att == \"rx\" && o.type == \"rect\") {\n break;\n }\n case \"cx\":\n node.setAttribute(att, value);\n o.pattern && updatePosition(o);\n o._.dirty = 1;\n break;
57601\n case \"height\":\n node.setAttribute(att, value);\n o._.dirty = 1;\n if (attrs.fy) {\n att = \"y\";\n value = attrs.y;\n } else {\n break;\n }\n case \"y\":\n if (attrs.fy) {\n value = -attrs.y - (attrs.height || 0);\n }\n case \"ry\":\n if (att == \"ry\" && o.type == \"rect\") {\n break;\n }\n case \"cy\":\n node.setAttribute(att, value);\n o.pattern && updatePosition(o);\n o._.dirty = 1;\n break;\n case \"r\":\n if (o.type == \"rect\") {\n $(node, {rx: value, ry: value});\n } else {\n node.setAttribute(att, value);\n }\n o._.dirty = 1;\n break;\n case \"src\":\n if (o.type == \"image\") {\n node.setAttributeNS(xlink, \"href\", value);\n }\n break;\n case \"stroke-width\":\n if (o._.sx != 1 || o._.sy != 1) {\n value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;\n }\n node.setAttribute(att, value);\n if (attrs[\"stroke-dasharray\"]) {\n addDashes(o, attrs[\"stroke-dasharray\"], params);\n }\n if (o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n break;\n case \"stroke-dasharray\":\n addDashes(o, value, params);\n break;\n case \"fill\":\n var isURL = Str(value).match(R._ISURL);\n if (isURL) {\n el = $(\"pattern\");\n var ig = $(\"image\");\n el.id = R.createUUID();\n $(el, {x: 0, y: 0, patternUnits: \"userSpaceOnUse\", height: 1, width: 1});\n $(ig, {x: 0, y: 0, \"xlink:href\": isURL[1]});\n el.appendChild(ig);\n\n (function (el) {\n R._preload(isURL[1], function () {\n var w = this.offsetWidth,\n h = this.offsetHeight;\n $(el, {width: w, height: h});\n $(ig, {width: w, height: h});\n });\n })(el);\n o.paper.defs.appendChild(el);\n $(node, {fill: \"url(#\" + el.id + \")\"});\n o.pattern = el;\n o.pattern && updatePosition(o);\n break;\n }\n var clr = R.getRGB(value);\n if (!clr.error) {\n delete params.gradient;\n delete attrs.gradient;\n !R.is(attrs.opacity, \"undefined\") &&\n R.is(params.opacity, \"undefined\") &&\n $(node, {opacity: attrs.opacity});\n !R.is(attrs[\"fill-opacity\"], \"undefined\") &&\n R.is(params[\"fill-opacity\"], \"undefined\") &&\n $(node, {\"fill-opacity\": attrs[\"fill-opacity\"]});\n } else if ((o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value)) {\n if (\"opacity\" in attrs || \"fill-opacity\" in attrs) {\n var gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n if (gradient) {\n var stops = gradient.getElementsByTagName(\"stop\");\n $(stops[stops.length - 1], {\"stop-opacity\": (\"opacity\" in attrs ? attrs.opacity : 1) * (\"fill-opacity\" in attrs ? attrs[\"fill-opacity\"] : 1)});\n }\n }\n attrs.gradient = value;\n attrs.fill = \"none\";\n break;\n }\n clr[has](\"opacity\") && $(node, {\"fill-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n case \"stroke\":\n clr = R.getRGB(value);\n node.setAttribute(att, clr.hex);\n att == \"stroke\" && clr[has](\"opacity\") && $(node, {\"stroke-opacity\": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});\n if (att == \"stroke\" && o._.arrows) {\n \"startString\" in o._.arrows && addArrow(o, o._.arrows.startString);\n \"endString\" in o._.arrows && addArrow(o, o._.arrows.endString, 1);\n }\n break;\n case \"gradient\":\n (o.type == \"circle\" || o.type == \"ellipse\" || Str(value).charAt() != \"r\") && addGradientFill(o, value);\n break;\n case \"opacity\":\n if (attrs.gradient && !attrs[has](\"stroke-opacity\")) {\n $(node, {\"stroke-opacity\": value > 1 ? value / 100 : value});\n }\n // fall\n case \"fill-opacity\":\n if (attrs.gradient) {\n gradient = R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g, E));\n if (gradient) {\n stops = gradient.getElementsByTagName(\"stop\");\n $(stops[stops.length - 1], {\"stop-opacity\": value});\n }\n break;\n }\n default:\n att == \"font-size\" && (value = toInt(value, 10) + \"px\");\n var cssrule = att.replace(/(\\-.)/g, function (w) {\n return w.substring(1).toUpperCase();\n });\n node.style[cssrule] = value;\n o._.dirty = 1;\n node.setAttribute(att, value);\n break;\n }\n }\n }\n\n tuneText(o, params);\n node.style.visibility = vis;\n },\n leading = 1.2,\n tuneText = function (el, params) {\n if (el.type != \"text\" || !(params[has](\"text\") || params[has](\"font\") || params[has](\"font-size\") || params[has](\"x\") || params[has](\"y\"))) {\n return;\n }\n var a = el.attrs,\n node = el.node,\n fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue(\"font-size\"), 10) : 10;\n\n if (params[has](\"text\")) {\n a.text = params.text;\n while (node.firstChild) {\n node.removeChild(node.firstChild);\n }\n var texts = Str(params.text).split(\"\\n\"),\n tspans = [],\n tspan;\n for (var i = 0, ii = texts.length; i < ii;
57601 i++) {\n tspan = $(\"tspan\");\n i && $(tspan, {dy: fontSize * leading, x: a.x});\n tspan.appendChild(R._g.doc.createTextNode(texts[i]));\n node.appendChild(tspan);\n tspans[i] = tspan;\n }\n } else {\n tspans = node.getElementsByTagName(\"tspan\");\n for (i = 0, ii = tspans.length; i < ii; i++) if (i) {\n $(tspans[i], {dy: fontSize * leading, x: a.x});\n } else {\n $(tspans[0], {dy: 0});\n }\n }\n $(node, {x: a.x, y: a.y});\n el._.dirty = 1;\n var bb = el._getBBox(),\n dif = a.y - (bb.y + bb.height / 2);\n dif && R.is(dif, \"finite\") && $(tspans[0], {dy: dif});\n },\n getRealNode = function (node) {\n if (node.parentNode && node.parentNode.tagName.toLowerCase() === \"a\") {\n return node.parentNode;\n } else {\n return node;\n }\n },\n Element = function (node, svg) {\n var X = 0,\n Y = 0;\n /*\\\n * Element.node\n [ property (object) ]\n **\n * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.\n **\n * Note: Donât mess with it.\n > Usage\n | // draw a circle at coordinate 10,10 with radius of 10\n | var c = paper.circle(10, 10, 10);\n | c.node.onclick = function () {\n | c.attr(\"fill\", \"red\");\n | };\n \\*/\n this[0] = this.node = node;\n /*\\\n * Element.raphael\n [ property (object) ]\n **\n * Internal reference to @Raphael object. In case it is not available.\n > Usage\n | Raphael.el.red = function () {\n | var hsb = this.paper.raphael.rgb2hsb(this.attr(\"fill\"));\n | hsb.h = 1;\n | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});\n | }\n \\*/\n node.raphael = true;\n /*\\\n * Element.id\n [ property (number) ]\n **\n * Unique id of the element. Especially useful when you want to listen to events of the element,\n * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.\n \\*/\n this.id = guid();\n node.raphaelid = this.id;\n\n /**\n * Method that returns a 5 letter/digit id, enough for 36^5 = 60466176 elements\n * @returns {string} id\n */\n function guid() {\n return (\"0000\" + (Math.random()*Math.pow(36,5) << 0).toString(36)).slice(-5);\n }\n\n this.matrix = R.matrix();\n this.realPath = null;\n /*\\\n * Element.paper\n [ property (object) ]\n **\n * Internal reference to âpaperâ where object drawn. Mainly for use in plugins and element extensions.\n > Usage\n | Raphael.el.cross = function () {\n | this.attr({fill: \"red\"});\n | this.paper.path(\"M10,10L50,50M50,10L10,50\")\n | .attr({stroke: \"red\"});\n | }\n \\*/\n this.paper = svg;\n this.attrs = this.attrs || {};\n this._ = {\n transform: [],\n sx: 1,\n sy: 1,\n deg: 0,\n dx: 0,\n dy: 0,\n dirty: 1\n };\n !svg.bottom && (svg.bottom = this);\n /*\\\n * Element.prev\n [ property (object) ]\n **\n * Reference to the previous element in the hierarchy.\n \\*/\n this.prev = svg.top;\n svg.top && (svg.top.next = this);\n svg.top = this;\n /*\\\n * Element.next\n [ property (object) ]\n **\n * Reference to the next element in the hierarchy.\n \\*/\n this.next = null;\n },\n elproto = R.el;\n\n Element.prototype = elproto;\n elproto.constructor = Element;\n\n R._engine.path = function (pathString, SVG) {\n var el = $(\"path\");\n SVG.canvas && SVG.canvas.appendChild(el);\n var p = new Element(el, SVG);\n p.type = \"path\";\n setFillAndStroke(p, {\n fill: \"none\",\n stroke: \"#000\",\n path: pathString\n });\n return p;\n };\n /*\\\n * Element.rotate\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds rotation by given angle around given point to the list of\
57601n * transformations of the element.\n > Parameters\n - deg (number) angle in degrees\n - cx (number) #optional x coordinate of the centre of rotation\n - cy (number) #optional y coordinate of the centre of rotation\n * If cx & cy arenât specified centre of the shape is used as a point of rotation.\n = (object) @Element\n \\*/\n elproto.rotate = function (deg, cx, cy) {\n if (this.removed) {\n return this;\n }\n deg = Str(deg).split(separator);\n if (deg.length - 1) {\n cx = toFloat(deg[1]);\n cy = toFloat(deg[2]);\n }\n deg = toFloat(deg[0]);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n cx = bbox.x + bbox.width / 2;\n cy = bbox.y + bbox.height / 2;\n }\n this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n return this;\n };\n /*\\\n * Element.scale\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds scale by given amount relative to given point to the list of\n * transformations of the element.\n > Parameters\n - sx (number) horisontal scale amount\n - sy (number) vertical scale amount\n - cx (number) #optional x coordinate of the centre of scale\n - cy (number) #optional y coordinate of the centre of scale\n * If cx & cy arenât specified centre of the shape is used instead.\n = (object) @Element\n \\*/\n elproto.scale = function (sx, sy, cx, cy) {\n if (this.removed) {\n return this;\n }\n sx = Str(sx).split(separator);\n if (sx.length - 1) {\n sy = toFloat(sx[1]);\n cx = toFloat(sx[2]);\n cy = toFloat(sx[3]);\n }\n sx = toFloat(sx[0]);\n (sy == null) && (sy = sx);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n }\n cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n return this;\n };\n /*\\\n * Element.translate\n [ method ]\n **\n * Deprecated! Use @Element.transform instead.\n * Adds translation by given amount to the list of transformations of the element.\n > Parameters\n - dx (number) horisontal shift\n - dy (number) vertical shift\n = (object) @Element\n \\*/\n elproto.translate = function (dx, dy) {\n if (this.removed) {\n return this;\n }\n dx = Str(dx).split(separator);\n if (dx.length - 1) {\n dy = toFloat(dx[1]);\n }\n dx = toFloat(dx[0]) || 0;\n dy = +dy || 0;\n this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n return this;\n };\n /*\\\n * Element.transform\n [ method ]\n **\n * Adds transformation to the element which is separate to other attributes,\n * i.e. translation doesnât change `x` or `y` of the rectange. The format\n * of transformation string is similar to the path string syntax:\n | \"t100,100r30,100,100s2,2,100,100r45s1.5\"\n * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for\n * scale and `m` is for matrix.\n *\n * There are also alternative âabsoluteâ translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.\n *\n * So, the example line above could be read like âtranslate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;\n * rotate 45° around centre; scale 1.5 times relative to centreâ. As you can see rotate and scale commands have origin\n * coordinates as optional parameters, the default is the centre point of the element.\n * Matrix accepts six parameters.\n > Usage\n | var el = paper.rect(10, 20, 300, 200);\n | // translate 100, 100, rotate 45°, translate -100, 0\n | el.transform(\"t100,100r45t-100,0\");\n | // if you want you can append or prepend transformations\n | el.transform(\"...t50,50\");\n | el.transform(\"s2...\");\n | // or even wrap\n | el.transform(\"t50,50...t-50-50\");\n | // to reset transformation call method with empty string\n | el.transform(\"\");\n | // to get current value call it without parameters\n | console.log(el.transform());\n > Parameters\n - tstr (string) #optional transformation string\n * If tstr isnât specified\n = (string) current transformation string\n * else\n = (object) @Element\n \\*/\n elproto.transform = function (tstr) {\n var _ = this._;\n if (tstr == null) {\n return _.transform;\n }\n R._extractTransform(this, tstr);\n\n this.clip && $(this.clip, {transform: this.matrix.invert()});\n this.pattern && updatePosition(this);\n this.node && $(this.node, {transform: this.matrix});\n\n if (_.sx != 1 || _.sy != 1) {\n var sw = this.attrs[has](\"stroke-width\") ? this.attrs[\"stroke-width\"] : 1;\n this.attr({\"stroke-width\": sw}
57601);\n }\n\n return this;\n };\n /*\\\n * Element.hide\n [ method ]\n **\n * Makes element invisible. See @Element.show.\n = (object) @Element\n \\*/\n elproto.hide = function () {\n if(!this.removed) this.node.style.display = \"none\";\n return this;\n };\n /*\\\n * Element.show\n [ method ]\n **\n * Makes element visible. See @Element.hide.\n = (object) @Element\n \\*/\n elproto.show = function () {\n if(!this.removed) this.node.style.display = \"\";\n return this;\n };\n /*\\\n * Element.remove\n [ method ]\n **\n * Removes element from the paper.\n \\*/\n elproto.remove = function () {\n var node = getRealNode(this.node);\n if (this.removed || !node.parentNode) {\n return;\n }\n var paper = this.paper;\n paper.__set__ && paper.__set__.exclude(this);\n eve.unbind(\"raphael.*.*.\" + this.id);\n if (this.gradient) {\n paper.defs.removeChild(this.gradient);\n }\n R._tear(this, paper);\n\n node.parentNode.removeChild(node);\n\n // Remove custom data for element\n this.removeData();\n\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n this.removed = true;\n };\n elproto._getBBox = function () {\n if (this.node.style.display == \"none\") {\n this.show();\n var hide = true;\n }\n var canvasHidden = false,\n containerStyle;\n if (this.paper.canvas.parentElement) {\n containerStyle = this.paper.canvas.parentElement.style;\n } //IE10+ can't find parentElement\n else if (this.paper.canvas.parentNode) {\n containerStyle = this.paper.canvas.parentNode.style;\n }\n\n if(containerStyle && containerStyle.display == \"none\") {\n canvasHidden = true;\n containerStyle.display = \"\";\n }\n var bbox = {};\n try {\n bbox = this.node.getBBox();\n } catch(e) {\n // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix\n bbox = {\n x: this.node.clientLeft,\n y: this.node.clientTop,\n width: this.node.clientWidth,\n height: this.node.clientHeight\n }\n } finally {\n bbox = bbox || {};\n if(canvasHidden){\n containerStyle.display = \"none\";\n }\n }\n hide && this.hide();\n return bbox;\n };\n /*\\\n * Element.attr\n [ method ]\n **\n * Sets the attributes of the element.\n > Parameters\n - attrName (string) attributeâs name\n - value (string) value\n * or\n - params (object) object of name/value pairs\n * or\n - attrName (string) attributeâs name\n * or\n - attrNames (array) in this case method returns array of current values for given attribute names\n = (object) @Element if attrsName & value or params are passed in.\n = (...) value of the attribute if only attrsName is passed in.\n = (array) array of values of the attribute if attrsNames is passed in.\n = (object) object of attributes if nothing is passed in.\n > Possible parameters\n # <p>Please refer to the <a href=\"http://www.w3.org/TR/SVG/\" title=\"The W3C Recommendation for the SVG language describes these properties in detail.\">SVG specification</a> for an explanation of these parameters.</p>\n o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.\n o clip-rect (string) comma or space separated values: x, y, width and height\n o cursor (string) CSS type of the cursor\n o cx (number) the x-axis coordinate of the center of the circle, or ellipse\n o cy (number) the y-axis coordinate of the center of the circle, or ellipse\n o fill (string) colour, gradient or image\n o fill-opacity (number)\n o font (string)\n o font-family (string)\n o font-size (number) font size in pixels\n o font-weight (string)\n o height (number)\n o href (string) URL, if specified element behaves as hyperlink\n o opacity (number)\n o path (string) SVG path string format\n o r (number) radius of the circle, ellipse or rounded corner on the rect\n o rx (number) horisontal radius of the ellipse\n o ry (number) vertical radius of the ellipse\n o src (string) image URL, only works for @Element.image element\n o stroke (string) stroke colour\n o stroke-dasharray (string) [ââ, ânoneâ, â`-`â, â`.`â, â`-.`â, â`-..`â, â`. `â, â`- `â, â`--`â, â`- .`â, â`--.`â, â`--..`â]\n o stroke-linecap (string) [â`butt`â, â`square`â, â`round`â]\n o stroke-linejoin (string) [â`bevel`â, â`round`â, â`miter`â]\n o stroke-miterlimit (number)\n o stroke-opacity (number)\n o stroke-width (number) stroke width in pixels, default is '1'\n o target (string) used with href\n o text (string) contents of the text element. Use `\\n` for multiline text\n o text-anchor (string) [â`start`â, â`middle`â, â`end`â
57601], default is â`middle`â\n o title (string) will create tooltip with a given text\n o transform (string) see @Element.transform\n o width (number)\n o x (number)\n o y (number)\n > Gradients\n * Linear gradient format: â`â¹angleâº-â¹colourâº[-â¹colourâº[:â¹offsetâº]]*-â¹colourâº`â, example: â`90-#fff-#000`â â 90°\n * gradient from white to black or â`0-#fff-#f00:20-#000`â â 0° gradient from white via red (at 20%) to black.\n *\n * radial gradient: â`r[(â¹fxâº, â¹fyâº)]â¹colourâº[-â¹colourâº[:â¹offsetâº]]*-â¹colourâº`â, example: â`r#fff-#000`â â\n * gradient from white to black or â`r(0.25, 0.75)#fff-#000`â â gradient from white to black with focus point\n * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.\n > Path String\n # <p>Please refer to <a href=\"http://www.w3.org/TR/SVG/paths.html#PathData\" title=\"Details of a pathâs data attributeâs format are described in the SVG specification.\">SVG documentation regarding path string</a>. Raphaël fully supports it.</p>\n > Colour Parsing\n # <ul>\n # <li>Colour name (â<code>red</code>â, â<code>green</code>â, â<code>cornflowerblue</code>â, etc)</li>\n # <li>#â¢â¢â¢ â shortened HTML colour: (â<code>#000</code>â, â<code>#fc0</code>â, etc)</li>\n # <li>#â¢â¢â¢â¢â¢â¢ â full length HTML colour: (â<code>#000000</code>â, â<code>#bd2300</code>â)</li>\n # <li>rgb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â red, green and blue channelsâ values: (â<code>rgb(200, 100, 0)</code>â)</li>\n # <li>rgb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgb(100%, 175%, 0%)</code>â)</li>\n # <li>rgba(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â red, green and blue channelsâ values: (â<code>rgba(200, 100, 0, .5)</code>â)</li>\n # <li>rgba(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %: (â<code>rgba(100%, 175%, 0%, 50%)</code>â)</li>\n # <li>hsb(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â hue, saturation and brightness values: (â<code>hsb(0.5, 0.25, 1)</code>â)</li>\n # <li>hsb(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %</li>\n # <li>hsba(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â same as above, but with opacity</li>\n # <li>hsl(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â almost the same as hsb, see <a href=\"http://en.wikipedia.org/wiki/HSL_and_HSV\" title=\"HSL and HSV - Wikipedia, the free encyclopedia\">Wikipedia page</a></li>\n # <li>hsl(â¢â¢â¢%, â¢â¢â¢%, â¢â¢â¢%) â same as above, but in %</li>\n # <li>hsla(â¢â¢â¢, â¢â¢â¢, â¢â¢â¢, â¢â¢â¢) â same as above, but with opacity</li>\n # <li>Optionally for hsb and hsl you could specify hue as a degree: â<code>hsl(240deg, 1, .5)</code>â or, if you want to go fancy, â<code>hsl(240°, 1, .5)</code>â</li>\n # </ul>\n \\*/\n elproto.attr = function (name, value) {\n if (this.removed) {\n return this;\n }\n if (name == null) {\n var res = {};\n for (var a in this.attrs) if (this.attrs[has](a)) {\n res[a] = this.attrs[a];\n }\n res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n res.transform = this._.transform;\n return res;\n }\n if (value == null && R.is(name, \"string\")) {\n if (name == \"fill\" && this.attrs.fill == \"none\" && this.attrs.gradient) {\n return this.attrs.gradient;\n }\n if (name == \"transform\") {\n return this._.transform;\n }\n var names = name.split(separator),\n out = {};\n for (var i = 0, ii = names.length; i < ii;
57601 i++) {\n name = names[i];\n if (name in this.attrs) {\n out[name] = this.attrs[name];\n } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n out[name] = this.paper.customAttributes[name].def;\n } else {\n out[name] = R._availableAttrs[name];\n }\n }\n return ii - 1 ? out : out[names[0]];\n }\n if (value == null && R.is(name, \"array\")) {\n out = {};\n for (i = 0, ii = name.length; i < ii; i++) {\n out[name[i]] = this.attr(name[i]);\n }\n return out;\n }\n if (value != null) {\n var params = {};\n params[name] = value;\n } else if (name != null && R.is(name, \"object\")) {\n params = name;\n }\n for (var key in params) {\n eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n }\n for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n this.attrs[key] = params[key];\n for (var subkey in par) if (par[has](subkey)) {\n params[subkey] = par[subkey];\n }\n }\n setFillAndStroke(this, params);\n return this;\n };\n /*\\\n * Element.toFront\n [ method ]\n **\n * Moves the element so it is the closest to the viewerâs eyes, on top of other elements.\n = (object) @Element\n \\*/\n elproto.toFront = function () {\n if (this.removed) {\n return this;\n }\n var node = getRealNode(this.node);\n node.parentNode.appendChild(node);\n var svg = this.paper;\n svg.top != this && R._tofront(this, svg);\n return this;\n };\n /*\\\n * Element.toBack\n [ method ]\n **\n * Moves the element so it is the furthest from the viewerâs eyes, behind other elements.\n = (object) @Element\n \\*/\n elproto.toBack = function () {\n if (this.removed) {\n return this;\n }\n var node = getRealNode(this.node);\n var parentNode = node.parentNode;\n parentNode.insertBefore(node, parentNode.firstChild);\n R._toback(this, this.paper);\n var svg = this.paper;\n return this;\n };\n /*\\\n * Element.insertAfter\n [ method ]\n **\n * Inserts current object after the given one.\n = (object) @Element\n \\*/\n elproto.insertAfter = function (element) {\n if (this.removed || !element) {\n return this;\n }\n\n var node = getRealNode(this.node);\n var afterNode = getRealNode(element.node || element[element.length - 1].node);\n if (afterNode.nextSibling) {\n afterNode.parentNode.insertBefore(node, afterNode.nextSibling);\n } else {\n afterNode.parentNode.appendChild(node);\n }\n R._insertafter(this, element, this.paper);\n return this;\n };\n /*\\\n * Element.insertBefore\n [ method ]\n **\n * Inserts current object before the given one.\n = (object) @Element\n \\*/\n elproto.insertBefore = function (element) {\n if (this.removed || !element) {\n return this;\n }\n\n var node = getRealNode(this.node);\n var beforeNode = getRealNode(element.node || element[0].node);\n beforeNode.parentNode.insertBefore(node, beforeNode);\n R._insertbefore(this, element, this.paper);\n return this;\n };\n elproto.blur = function (size) {\n // Experimental. No Safari support. Use it on your own risk.\n var t = this;\n if (+size !== 0) {\n var fltr = $(\"filter\"),\n blur = $(\"feGaussianBlur\");\n t.attrs.blur = size;\n fltr.id = R.createUUID();\n $(blur, {stdDeviation: +size || 1.5});\n fltr.appendChild(blur);\n t.paper.defs.appendChild(fltr);\n t._blur = fltr;\n $(t.node, {filter: \"url(#\" + fltr.id + \")\"});\n } else {\n if (t._blur) {\n t._blur.parentNode.removeChild(t._blur);\n delete t._blur;\n delete t.attrs.blur;\n }\n t.node.removeAttribute(\"filter\");\n }\n return t;\n };\n R._engine.circle = function (svg, x, y, r) {\n var el = $(\"circle\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {cx: x, cy: y, r: r, fill: \"none\", stroke: \"#000\"};\n res.type = \"circle\";\n $(el, res.attrs);\n return res;\n };\n R._engine.rect = function (svg, x, y, w, h, r) {\n var el = $(\"rect\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: \"none\", stroke: \"#000\"};\n res.type = \"rect\";\n $(el, res.attrs);\n return res;\n };\n R._engine.ellipse = function (svg, x, y, rx, ry) {\n var el = $(\"ellipse\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: \"none\", stroke: \"#000\"};\n res.type = \"ellipse\";\n $(el, res.attrs);\n return res;\n };\n R._engine.image = function (svg, src, x, y, w, h) {\n var el = $(\"image\");\n $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: \"none\"});\n el.setAttributeNS(xlink, \"href\", src);\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {x: x, y: y, width: w, height: h, src: src};\n res.type = \"image\";\n return res;\n };\n R._engine.text = function (svg, x, y, text) {\n var el = $(\"text\");\n svg.canvas && svg.canvas.appendChild(el);\n var res = new Element(el, svg);\n res.attrs = {\n x: x,\n y: y,\n \"text-anchor\": \"middle\",\n text: text,\n \"font-family\": R._availableAttrs[\"font-family\"],\n \"font-size\": R._availableAttrs[\"font-size\"],\n stroke: \"none\",\n fill: \"#000\"\n };\n res.type = \"text\";\n setFillAndStroke(res, res.attrs);\n return res;\n };\n R._engine.setSize = function (width, height) {\n this.width = width || this.width;\n this.height = height || this.height;\n this.canvas.setAttribute(\"width\", this.width);\n this.canvas.setAttribute(\"height\", this.height);\n if (this._viewBox) {\n this.setViewBox.apply(this, this._viewBox);\n }\n return this;\n };\n R._engine.create = function () {\n var con = R._getContainer.apply(0, arguments),\n container = con && con.container;\n if (!container) {\n throw new Error(\"SVG container not found.\");\n }\n var x = con.x,\n y = con.y,\n width = con.width,\n height = con.height,\n cnvs = $(\"svg\"),\n css = \"overflow:hidden;\",\n isFloating;\n x = x || 0;\n y = y || 0;\n width = width || 512;\n height = height || 342;
57601\n $(cnvs, {\n height: height,\n version: 1.1,\n width: width,\n xmlns: \"http://www.w3.org/2000/svg\",\n \"xmlns:xlink\": \"http://www.w3.org/1999/xlink\"\n });\n if (container == 1) {\n cnvs.style.cssText = css + \"position:absolute;left:\" + x + \"px;top:\" + y + \"px\";\n R._g.doc.body.appendChild(cnvs);\n isFloating = 1;\n } else {\n cnvs.style.cssText = css + \"position:relative\";\n if (container.firstChild) {\n container.insertBefore(cnvs, container.firstChild);\n } else {\n container.appendChild(cnvs);\n }\n }\n container = new R._Paper;\n container.width = width;\n container.height = height;\n container.canvas = cnvs;\n container.clear();\n container._left = container._top = 0;\n isFloating && (container.renderfix = function () {});\n container.renderfix();\n return container;\n };\n R._engine.setViewBox = function (x, y, w, h, fit) {\n eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n var paperSize = this.getSize(),\n size = mmax(w / paperSize.width, h / paperSize.height),\n top = this.top,\n aspectRatio = fit ? \"xMidYMid meet\" : \"xMinYMin\",\n vb,\n sw;\n if (x == null) {\n if (this._vbSize) {\n size = 1;\n }\n delete this._vbSize;\n vb = \"0 0 \" + this.width + S + this.height;\n } else {\n this._vbSize = size;\n vb = x + S + y + S + w + S + h;\n }
57601\n $(this.canvas, {\n viewBox: vb,\n preserveAspectRatio: aspectRatio\n });\n while (size && top) {\n sw = \"stroke-width\" in top.attrs ? top.attrs[\"stroke-width\"] : 1;\n top.attr({\"stroke-width\": sw});\n top._.dirty = 1;\n top._.dirtyT = 1;\n top = top.prev;\n }\n this._viewBox = [x, y, w, h, !!fit];\n return this;\n };\n /*\\\n * Paper.renderfix\n [ method ]\n **\n * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependent\n * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.\n * This method fixes the issue.\n **\n Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.\n \\*/\n R.prototype.renderfix = function () {\n var cnvs = this.canvas,\n s = cnvs.style,\n pos;\n try {\n pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();\n } catch (e) {\n pos = cnvs.createSVGMatrix();\n }\n var left = -pos.e % 1,\n top = -pos.f % 1;\n if (left || top) {\n if (left) {\n this._left = (this._left + left) % 1;\n s.left = this._left + \"px\";\n }\n if (top) {\n this._top = (this._top + top) % 1;\n s.top = this._top + \"px\";\n }\n }\n };\n /*\\\n * Paper.clear\n [ method ]\n **\n * Clears the paper, i.e. removes all the elements.\n \\*/\n R.prototype.clear = function () {\n R.eve(\"raphael.clear\", this);\n var c = this.canvas;\n while (c.firstChild) {\n c.removeChild(c.firstChild);\n }\n this.bottom = this.top = null;\n (this.desc = $(\"desc\")).appendChild(R._g.doc.createTextNode(\"Created with Rapha\\xebl \" + R.version));\n c.appendChild(this.desc);\n c.appendChild(this.defs = $(\"defs\"));\n };\n /*\\\n * Paper.remove\n [ method ]\n **\n * Removes the paper from the DOM.\n \\*/\n R.prototype.remove = function () {\n eve(\"raphael.remove\", this);\n this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n };\n var setproto = R.st;\n for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname].apply(el, arg);\n });\n };\n })(method);\n }\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC5zdmcuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwuc3ZnLmpzP2Q4YzciXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCJdLCBmdW5jdGlvbihSKSB7XG4gICAgaWYgKFIgJiYgIVIuc3ZnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaGFzID0gXCJoYXNPd25Qcm9wZXJ0eVwiLFxuICAgICAgICBTdHIgPSBTdHJpbmcsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICB0b0ludCA9IHBhcnNlSW50LFxuICAgICAgICBtYXRoID0gTWF0aCxcbiAgICAgICAgbW1heCA9IG1hdGgubWF4LFxuICAgICAgICBhYnMgPSBtYXRoLmFicyxcbiAgICAgICAgcG93ID0gbWF0aC5wb3csXG4gICAgICAgIHNlcGFyYXRvciA9IC9bLCBdKy8sXG4gICAgICAgIGV2ZSA9IFIuZXZlLFxuICAgICAgICBFID0gXCJcIixcbiAgICAgICAgUyA9IFwiIFwiO1xuICAgIHZhciB4bGluayA9IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiLFxuICAgICAgICBtYXJrZXJzID0ge1xuICAgICAgICAgICAgYmxvY2s6IFwiTTUsMCAwLDIuNSA1LDV6XCIsXG4gICAgICAgICAgICBjbGFzc2ljOiBcIk01LDAgMCwyLjUgNSw1IDMuNSwzIDMuNSwyelwiLFxuICAgICAgICAgICAgZGlhbW9uZDogXCJNMi41LDAgNSwyLjUgMi41LDUgMCwyLjV6XCIsXG4gICAgICAgICAgICBvcGVuOiBcIk02LDEgMSwzLjUgNiw2XCIsXG4gICAgICAgICAgICBvdmFsOiBcIk0yLjUsMEEyLjUsMi41LDAsMCwxLDIuNSw1IDIuNSwyLjUsMCwwLDEsMi41LDB6XCJcbiAgICAgICAgfSxcbiAgICAgICAgbWFya2VyQ291bnRlciA9IHt9O1xuICAgIFIudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgI
57601HJldHVybiAgXCJZb3VyIGJyb3dzZXIgc3VwcG9ydHMgU1ZHLlxcbllvdSBhcmUgcnVubmluZyBSYXBoYVxceGVibCBcIiArIHRoaXMudmVyc2lvbjtcbiAgICB9O1xuICAgIHZhciAkID0gZnVuY3Rpb24gKGVsLCBhdHRyKSB7XG4gICAgICAgIGlmIChhdHRyKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVsID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBlbCA9ICQoZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGF0dHIpIGlmIChhdHRyW2hhc10oa2V5KSkge1xuICAgICAgICAgICAgICAgIGlmIChrZXkuc3Vic3RyaW5nKDAsIDYpID09IFwieGxpbms6XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuc2V0QXR0cmlidXRlTlMoeGxpbmssIGtleS5zdWJzdHJpbmcoNiksIFN0cihhdHRyW2tleV0pKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoa2V5LCBTdHIoYXR0cltrZXldKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWwgPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCBlbCk7XG4gICAgICAgICAgICBlbC5zdHlsZSAmJiAoZWwuc3R5bGUud2Via2l0VGFwSGlnaGxpZ2h0Q29sb3IgPSBcInJnYmEoMCwwLDAsMClcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH0sXG4gICAgYWRkR3JhZGllbnRGaWxsID0gZnVuY3Rpb24gKGVsZW1lbnQsIGdyYWRpZW50KSB7XG4gICAgICAgIHZhciB0eXBlID0gXCJsaW5lYXJcIixcbiAgICAgICAgICAgIGlkID0gZWxlbWVudC5pZCArIGdyYWRpZW50LFxuICAgICAgICAgICAgZnggPSAuNSwgZnkgPSAuNSxcbiAgICAgICAgICAgIG8gPSBlbGVtZW50Lm5vZGUsXG4gICAgICAgICAgICBTVkcgPSBlbGVtZW50LnBhcGVyLFxuICAgICAgICAgICAgcyA9IG8uc3R5bGUsXG4gICAgICAgICAgICBlbCA9IFIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKGlkKTtcbiAgICAgICAgaWYgKCFlbCkge1xuICAgICAgICAgICAgZ3JhZGllbnQgPSBTdHIoZ3JhZGllbnQpLnJlcGxhY2UoUi5fcmFkaWFsX2dyYWRpZW50LCBmdW5jdGlvbiAoYWxsLCBfZngsIF9meSkge1xuICAgICAgICAgICAgICAgIHR5cGUgPSBcInJhZGlhbFwiO1xuICAgICAgICAgICAgICAgIGlmIChfZnggJiYgX2Z5KSB7XG4gICAgICAgICAgICAgICAgICAgIGZ4ID0gdG9GbG9hdChfZngpO1xuICAgICAgICAgICAgICAgICAgICBmeSA9IHRvRmxvYXQoX2Z5KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpciA9ICgoZnkgPiAuNSkgKiAyIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIHBvdyhmeCAtIC41LCAyKSArIHBvdyhmeSAtIC41LCAyKSA+IC4yNSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKGZ5ID0gbWF0aC5zcXJ0KC4yNSAtIHBvdyhmeCAtIC41LCAyKSkgKiBkaXIgKyAuNSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ5ICE9IC41ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAoZnkgPSBmeS50b0ZpeGVkKDUpIC0gMWUtNSAqIGRpcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBFO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBncmFkaWVudCA9IGdyYWRpZW50LnNwbGl0KC9cXHMqXFwtXFxzKi8pO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJsaW5lYXJcIikge1xuICAgICAgICAgICAgICAgIHZhciBhbmdsZSA9IGdyYWRpZW50LnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgYW5nbGUgPSAtdG9GbG9hdChhbmdsZSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzTmFOKGFuZ2xlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHZlY3RvciA9IFswLCAwLCBtYXRoLmNvcyhSLnJhZChhbmdsZSkpLCBtYXRoLnNpbihSLnJhZChhbmdsZSkpXSxcbiAgICAgICAgICAgICAgICAgICAgbWF4ID0gMSAvIChtbWF4KGFicyh2ZWN0b3JbMl0pLCBhYnModmVjdG9yWzNdKSkgfHwgMSk7XG4gICAgICAgICAgICAgICAgdmVjdG9yWzJdICo9IG1heDtcbiAgICAgICAgICAgICAgICB2ZWN0b3JbM10gKj0gbWF4O1xuICAgICAgICAgICAgICAgIGlmICh2ZWN0b3JbMl0gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclswXSA9IC12ZWN0b3JbMl07XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclsyXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh2ZWN0b3JbM10gPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclsxXSA9IC12ZWN0b3JbM107XG4gICAgICAgICAgICAgICAgICAgIHZlY3RvclszXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRvdHMgPSBSLl9wYXJzZURvdHMoZ3JhZGllbnQpO1xuICAgICAgICAgICAgaWYgKCFkb3RzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZCA9IGlkLnJlcGxhY2UoL1tcXChcXClcXHMsXFx4YjAjXS9nLCBcIl9cIik7XG5cbiAgICAgICAgICAgIGlmIChlbGVtZW50LmdyYWRpZW50ICYmIGlkICE9IGVsZW1lbnQuZ3JhZGllbnQuaWQpIHtcbiAgICAgICAgICAgICAgICBTVkcuZGVmcy5yZW1vdmVDaGlsZChlbGVtZW50LmdyYWRpZW50KTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZWxlbWVudC5ncmFkaWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFlbGVtZW50LmdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgZWwgPSAkKHR5cGUgKyBcIkdyYWRpZW50XCIsIHtpZDogaWR9KTtcbiAgICAgICAgICAgICAgICBlbGVtZW50LmdyYWRpZW50ID0gZWw7XG4gICAgICAgICAgICAgICAgJChlbCwgdHlwZSA9PSBcInJhZGlhbFwiID8ge1xuICAgICAgICAgICAgICAgICAgICBmeDogZngsXG4gICAgICAgICAgICAgICAgICAgIGZ5OiBmeVxuICAgICAgICAgICAgICAgI
57601H0gOiB7XG4gICAgICAgICAgICAgICAgICAgIHgxOiB2ZWN0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIHkxOiB2ZWN0b3JbMV0sXG4gICAgICAgICAgICAgICAgICAgIHgyOiB2ZWN0b3JbMl0sXG4gICAgICAgICAgICAgICAgICAgIHkyOiB2ZWN0b3JbM10sXG4gICAgICAgICAgICAgICAgICAgIGdyYWRpZW50VHJhbnNmb3JtOiBlbGVtZW50Lm1hdHJpeC5pbnZlcnQoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIFNWRy5kZWZzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBkb3RzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoJChcInN0b3BcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0OiBkb3RzW2ldLm9mZnNldCA/IGRvdHNbaV0ub2Zmc2V0IDogaSA/IFwiMTAwJVwiIDogXCIwJVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJzdG9wLWNvbG9yXCI6IGRvdHNbaV0uY29sb3IgfHwgXCIjZmZmXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInN0b3Atb3BhY2l0eVwiOiBpc0Zpbml0ZShkb3RzW2ldLm9wYWNpdHkpID8gZG90c1tpXS5vcGFjaXR5IDogMVxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgICQobywge1xuICAgICAgICAgICAgZmlsbDogZmlsbHVybChpZCksXG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgXCJmaWxsLW9wYWNpdHlcIjogMVxuICAgICAgICB9KTtcbiAgICAgICAgcy5maWxsID0gRTtcbiAgICAgICAgcy5vcGFjaXR5ID0gMTtcbiAgICAgICAgcy5maWxsT3BhY2l0eSA9IDE7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH0sXG4gICAgaXNJRTlvcjEwID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG1vZGUgPSBkb2N1bWVudC5kb2N1bWVudE1vZGU7XG4gICAgICByZXR1cm4gbW9kZSAmJiAobW9kZSA9PT0gOSB8fCBtb2RlID09PSAxMCk7XG4gICAgfSxcbiAgICBmaWxsdXJsID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICBpZiAoaXNJRTlvcjEwKCkpIHtcbiAgICAgICAgICByZXR1cm4gXCJ1cmwoJyNcIiArIGlkICsgXCInKVwiO1xuICAgICAgfVxuICAgICAgdmFyIGxvY2F0aW9uID0gZG9jdW1lbnQubG9jYXRpb247XG4gICAgICB2Y
57601XIgbG9jYXRpb25TdHJpbmcgPSAoXG4gICAgICAgICAgbG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICtcbiAgICAgICAgICBsb2NhdGlvbi5ob3N0ICtcbiAgICAgICAgICBsb2NhdGlvbi5wYXRobmFtZSArXG4gICAgICAgICAgbG9jYXRpb24uc2VhcmNoXG4gICAgICApO1xuICAgICAgcmV0dXJuIFwidXJsKCdcIiArIGxvY2F0aW9uU3RyaW5nICsgXCIjXCIgKyBpZCArIFwiJylcIjtcbiAgICB9LFxuICAgIHVwZGF0ZVBvc2l0aW9uID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgdmFyIGJib3ggPSBvLmdldEJCb3goMSk7XG4gICAgICAgICQoby5wYXR0ZXJuLCB7cGF0dGVyblRyYW5zZm9ybTogby5tYXRyaXguaW52ZXJ0KCkgKyBcIiB0cmFuc2xhdGUoXCIgKyBiYm94LnggKyBcIixcIiArIGJib3gueSArIFwiKVwifSk7XG4gICAgfSxcbiAgICBhZGRBcnJvdyA9IGZ1bmN0aW9uIChvLCB2YWx1ZSwgaXNFbmQpIHtcbiAgICAgICAgaWYgKG8udHlwZSA9PSBcInBhdGhcIikge1xuICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFN0cih2YWx1ZSkudG9Mb3dlckNhc2UoKS5zcGxpdChcIi1cIiksXG4gICAgICAgICAgICAgICAgcCA9IG8ucGFwZXIsXG4gICAgICAgICAgICAgICAgc2UgPSBpc0VuZCA/IFwiZW5kXCIgOiBcInN0YXJ0XCIsXG4gICAgICAgICAgICAgICAgbm9kZSA9IG8ubm9kZSxcbiAgICAgICAgICAgICAgICBhdHRycyA9IG8uYXR0cnMsXG4gICAgICAgICAgICAgICAgc3Ryb2tlID0gYXR0cnNbXCJzdHJva2Utd2lkdGhcIl0sXG4gICAgICAgICAgICAgICAgaSA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgdHlwZSA9IFwiY2xhc3NpY1wiLFxuICAgICAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICAgICAgZHgsXG4gICAgICAgICAgICAgICAgcmVmWCxcbiAgICAgICAgICAgICAgICBhdHRyLFxuICAgICAgICAgICAgICAgIHcgPSAzLFxuICAgICAgICAgICAgICAgIGggPSAzLFxuICAgICAgICAgICAgICAgIHQgPSA1O1xuICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodmFsdWVzW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJibG9ja1wiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2xhc3NpY1wiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3ZhbFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZGlhbW9uZFwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3BlblwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwibm9uZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwid2lkZVwiOiBoID0gNTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJuYXJyb3dcIjogaCA9IDI7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwibG9uZ1wiOiB3ID0gNTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzaG9ydFwiOiB3ID0gMjsgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJvcGVuXCIpIHtcbiAgICAgICAgICAgICAgICB3ICs9IDI7XG4gICAgICAgICAgICAgICAgaCArPSAyO1xuICAgICAgICAgICAgICAgIHQgKz0gMjtcbiAgICAgICAgICAgICAgICBkeCA9IDE7XG4gICAgICAgICAgICAgICAgcmVmWCA9IGlzRW5kID8gNCA6IDE7XG4gICAgICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogXCJub25lXCIsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogYXR0cnMuc3Ryb2tlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVmWCA9IGR4ID0gdyAvIDI7XG4gICAgICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogYXR0cnMuc3Ryb2tlLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2U6IFwibm9uZVwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvLl8uYXJyb3dzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIG8uXy5hcnJvd3MuZW5kUGF0aCAmJiBtYXJrZXJDb3VudGVyW28uXy5hcnJvd3MuZW5kUGF0aF0tLTtcbiAgICAgICAgICAgICAgICAgICAgby5fLmFycm93cy5lbmRNYXJrZXIgJiYgbWFya2VyQ291bnRlcltvLl8uYXJyb3dzLmVuZE1hcmtlcl0tLTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvLl8uYXJyb3dzLnN0YXJ0UGF0aCAmJiBtYXJrZXJDb3VudGVyW28uXy5hcnJvd3Muc3RhcnRQYXRoXS0tO1xuICAgICAgICAgICAgICAgICAgICBvLl8uYXJyb3dzLnN0YXJ0TWFya2VyICYmIG1hcmtlckNvdW50ZXJbby5fLmFycm93cy5zdGFydE1hcmtlcl0tLTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3MgPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlICE9IFwibm9uZVwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGhJZCA9IFwicmFwaGFlbC1tYXJrZXItXCIgKyB0eXBlLFxuICAgICAgICAgICAgICAgICAgICBtYXJrZXJJZCA9IFwicmFwaGFlbC1tYXJrZXItXCIgKyBzZSArIHR5cGUgKyB3ICsgaCArIFwiLW9ialwiICsgby5pZDtcbiAgICAgICAgICAgICAgICBpZiAoIVIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKHBhdGhJZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcC5kZWZzLmFwcGVuZENoaWxkKCQoJChcInBhdGhcIiksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3Ryb2tlLWxpbmVjYXBcIjogXCJyb3VuZFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgZDogbWFya2Vyc1t0eXBlXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBwYXRoSWRcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXJDb3VudGVyW3BhdGhJZF0gPSAxO1xuICAgICAgICAgICAgICAgI
57601H0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlckNvdW50ZXJbcGF0aElkXSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbWFya2VyID0gUi5fZy5kb2MuZ2V0RWxlbWVudEJ5SWQobWFya2VySWQpLFxuICAgICAgICAgICAgICAgICAgICB1c2U7XG4gICAgICAgICAgICAgICAgaWYgKCFtYXJrZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFya2VyID0gJCgkKFwibWFya2VyXCIpLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZDogbWFya2VySWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJIZWlnaHQ6IGgsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXJXaWR0aDogdyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWVudDogXCJhdXRvXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWZYOiByZWZYLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmWTogaCAvIDJcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHVzZSA9ICQoJChcInVzZVwiKSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJ4bGluazpocmVmXCI6IFwiI1wiICsgcGF0aElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAoaXNFbmQgPyBcInJvdGF0ZSgxODAgXCIgKyB3IC8gMiArIFwiIFwiICsgaCAvIDIgKyBcIikgXCIgOiBFKSArIFwic2NhbGUoXCIgKyB3IC8gdCArIFwiLFwiICsgaCAvIHQgKyBcIilcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3Ryb2tlLXdpZHRoXCI6ICgxIC8gKCh3IC8gdCArIGggLyB0KSAvIDIpKS50b0ZpeGVkKDQpXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXIuYXBwZW5kQ2hpbGQodXNlKTtcbiAgICAgICAgICAgICAgICAgICAgcC5kZWZzLmFwcGVuZENoaWxkKG1hcmtlcik7XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlckNvdW50ZXJbbWFya2VySWRdID0gMTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXJDb3VudGVyW21hcmtlcklkXSsrO1xuICAgICAgICAgICAgICAgICAgICB1c2UgPSBtYXJrZXIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJ1c2VcIilbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICQodXNlLCBhdHRyKTtcbiAgICAgICAgICAgICAgICB2Y
57601XIgZGVsdGEgPSBkeCAqICh0eXBlICE9IFwiZGlhbW9uZFwiICYmIHR5cGUgIT0gXCJvdmFsXCIpO1xuICAgICAgICAgICAgICAgIGlmIChpc0VuZCkge1xuICAgICAgICAgICAgICAgICAgICBmcm9tID0gby5fLmFycm93cy5zdGFydGR4ICogc3Ryb2tlIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgIHRvID0gUi5nZXRUb3RhbExlbmd0aChhdHRycy5wYXRoKSAtIGRlbHRhICogc3Ryb2tlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBkZWx0YSAqIHN0cm9rZTtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gKG8uXy5hcnJvd3MuZW5kZHggKiBzdHJva2UgfHwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF0dHIgPSB7fTtcbiAgICAgICAgICAgICAgICBhdHRyW1wibWFya2VyLVwiICsgc2VdID0gXCJ1cmwoI1wiICsgbWFya2VySWQgKyBcIilcIjtcbiAgICAgICAgICAgICAgICBpZiAodG8gfHwgZnJvbSkge1xuICAgICAgICAgICAgICAgICAgICBhdHRyLmQgPSBSLmdldFN1YnBhdGgoYXR0cnMucGF0aCwgZnJvbSwgdG8pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkKG5vZGUsIGF0dHIpO1xuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3Nbc2UgKyBcIlBhdGhcIl0gPSBwYXRoSWQ7XG4gICAgICAgICAgICAgICAgby5fLmFycm93c1tzZSArIFwiTWFya2VyXCJdID0gbWFya2VySWQ7XG4gICAgICAgICAgICAgICAgby5fLmFycm93c1tzZSArIFwiZHhcIl0gPSBkZWx0YTtcbiAgICAgICAgICAgICAgICBvLl8uYXJyb3dzW3NlICsgXCJUeXBlXCJdID0gdHlwZTtcbiAgICAgICAgICAgICAgICBvLl8uYXJyb3dzW3NlICsgXCJTdHJpbmdcIl0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBvLl8uYXJyb3dzLnN0YXJ0ZHggKiBzdHJva2UgfHwgMDtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gZnJvbTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmcm9tID0gMDtcbiAgICAgICAgICAgICAgICAgICAgdG8gPSBSLmdldFRvdGFsTGVuZ3RoKGF0dHJzLnBhdGgpIC0gKG8uXy5hcnJvd3MuZW5kZHggKiBzdHJva2UgfHwgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG8uXy5hcnJvd3Nbc2UgKyBcIlBhdGhcIl0gJiYgJChub2RlLCB7ZDogUi5nZXRTdWJwYXRoKGF0dHJzLnBhdGgsIGZyb20sIHRvKX0pO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJQYXRoXCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJNYXJrZXJcIl07XG4gICAgICAgICAgICAgICAgZGVsZXRlIG8uXy5hcnJvd3Nbc2UgKyBcImR4XCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJUeXBlXCJdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvLl8uYXJyb3dzW3NlICsgXCJTdHJpbmdcIl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGF0dHIgaW4gbWFya2VyQ291bnRlcikgaWYgKG1hcmtlckNvdW50ZXJbaGFzXShhdHRyKSAmJiAhbWFya2VyQ291bnRlclthdHRyXSkge1xuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gUi5fZy5kb2MuZ2V0RWxlbWVudEJ5SWQoYXR0cik7XG4gICAgICAgICAgICAgICAgaXRlbSAmJiBpdGVtLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRhc2hhcnJheSA9IHtcbiAgICAgICAgXCItXCI6IFszLCAxXSxcbiAgICAgICAgXCIuXCI6IFsxLCAxXSxcbiAgICAgICAgXCItLlwiOiBbMywgMSwgMSwgMV0sXG4gICAgICAgIFwiLS4uXCI6IFszLCAxLCAxLCAxLCAxLCAxXSxcbiAgICAgICAgXCIuIFwiOiBbMSwgM10sXG4gICAgICAgIFwiLSBcIjogWzQsIDNdLFxuICAgICAgICBcIi0tXCI6IFs4LCAzXSxcbiAgICAgICAgXCItIC5cIjogWzQsI
57601DMsIDEsIDNdLFxuICAgICAgICBcIi0tLlwiOiBbOCwgMywgMSwgM10sXG4gICAgICAgIFwiLS0uLlwiOiBbOCwgMywgMSwgMywgMSwgM11cbiAgICB9LFxuICAgIGFkZERhc2hlcyA9IGZ1bmN0aW9uIChvLCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgICAgIHZhbHVlID0gZGFzaGFycmF5W1N0cih2YWx1ZSkudG9Mb3dlckNhc2UoKV07XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIHdpZHRoID0gby5hdHRyc1tcInN0cm9rZS13aWR0aFwiXSB8fCBcIjFcIixcbiAgICAgICAgICAgICAgICBidXR0ID0ge3JvdW5kOiB3aWR0aCwgc3F1YXJlOiB3aWR0aCwgYnV0dDogMH1bby5hdHRyc1tcInN0cm9rZS1saW5lY2FwXCJdIHx8IHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdXSB8fCAwLFxuICAgICAgICAgICAgICAgIGRhc2hlcyA9IFtdLFxuICAgICAgICAgICAgICAgIGkgPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgZGFzaGVzW2ldID0gdmFsdWVbaV0gKiB3aWR0aCArICgoaSAlIDIpID8gMSA6IC0xKSAqIGJ1dHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkKG8ubm9kZSwge1wic3Ryb2tlLWRhc2hhcnJheVwiOiBkYXNoZXMuam9pbihcIixcIil9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAkKG8ubm9kZSwge1wic3Ryb2tlLWRhc2hhcnJheVwiOiBcIm5vbmVcIn0pO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBzZXRGaWxsQW5kU3Ryb2tlID0gZnVuY3Rpb24gKG8sIHBhcmFtcykge1xuICAgICAgICB2Y
57601XIgbm9kZSA9IG8ubm9kZSxcbiAgICAgICAgICAgIGF0dHJzID0gby5hdHRycyxcbiAgICAgICAgICAgIHZpcyA9IG5vZGUuc3R5bGUudmlzaWJpbGl0eTtcbiAgICAgICAgbm9kZS5zdHlsZS52aXNpYmlsaXR5ID0gXCJoaWRkZW5cIjtcbiAgICAgICAgZm9yICh2YXIgYXR0IGluIHBhcmFtcykge1xuICAgICAgICAgICAgaWYgKHBhcmFtc1toYXNdKGF0dCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIVIuX2F2YWlsYWJsZUF0dHJzW2hhc10oYXR0KSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcGFyYW1zW2F0dF07XG4gICAgICAgICAgICAgICAgYXR0cnNbYXR0XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoYXR0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJibHVyXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBvLmJsdXIodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0aXRsZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRpdGxlID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShcInRpdGxlXCIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIGV4aXN0aW5nIDx0aXRsZT4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGl0bGUubGVuZ3RoICYmICh0aXRsZSA9IHRpdGxlWzBdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS5maXJzdENoaWxkLm5vZGVWYWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUgPSAkKFwidGl0bGVcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWwgPSBSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmFwcGVuZENoaWxkKHZhbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodGl0bGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJocmVmXCI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0YXJnZXRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbiA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwbi50YWdOYW1lLnRvTG93ZXJDYXNlKCkgIT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgaGwgPSAkKFwiYVwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbi5pbnNlcnRCZWZvcmUoaGwsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhsLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBuID0gaGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ID09IFwidGFyZ2V0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbi5zZXRBdHRyaWJ1dGVOUyh4bGluaywgXCJzaG93XCIsIHZhbHVlID09IFwiYmxhbmtcIiA/IFwibmV3XCIgOiB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBuLnNldEF0dHJpYnV0ZU5TKHhsaW5rLCBhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3Vyc29yXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlLmN1cnNvciA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJ0cmFuc2Zvcm1cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG8udHJhbnNmb3JtKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYXJyb3ctc3RhcnRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZEFycm93KG8sIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYXJyb3ctZW5kXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRBcnJvdyhvLCB2YWx1ZSwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImNsaXAtcmVjdFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlY3QgPSBTdHIodmFsdWUpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVjdC5sZW5ndGggPT0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8uY2xpcCAmJiBvLmNsaXAucGFyZW50Tm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG8uY2xpcC5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgZWwgPSAkKFwiY2xpcFBhdGhcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJjID0gJChcInJlY3RcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHJjLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg6IHJlY3RbMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk6IHJlY3RbMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiByZWN0WzJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHJlY3RbM11cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5hcHBlbmRDaGlsZChyYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5wYXBlci5kZWZzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcImNsaXAtcGF0aFwiOiBcInVybCgjXCIgKyBlbC5pZCArIFwiKVwifSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5jbGlwID0gcmM7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBhdGggPSBub2RlLmdldEF0dHJpYnV0ZShcImNsaXAtcGF0aFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGF0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgY2xpcCA9IFIuX2cuZG9jLmdldEVsZW1lbnRCeUlkKHBhdGgucmVwbGFjZSgvKF51cmxcXCgjfFxcKSQpL2csIEUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcCAmJiBjbGlwLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY2xpcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge1wiY2xpcC1wYXRoXCI6IEV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG8uY2xpcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8udHlwZSA9PSBcInBhdGhcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge2Q6IHZhbHVlID8gYXR0cnMucGF0aCA9IFIuX3BhdGhUb0Fic29sdXRlKHZhbHVlKSA6IFwiTTAsMFwifSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoby5fLmFycm93cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0YXJ0U3RyaW5nXCIgaW4gby5fLmFycm93cyAmJiBhZGRBcnJvdyhvLCBvLl8uYXJyb3dzLnN0YXJ0U3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJlbmRTdHJpbmdcIiBpbiBvLl8uYXJyb3dzICYmIGFkZEFycm93KG8sIG8uXy5hcnJvd3MuZW5kU3RyaW5nLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIndpZHRoXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0cnMuZngpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHQgPSBcInhcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGF0dHJzLng7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwieFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmZ4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSAtYXR0cnMueCAtIChhdHRycy53aWR0aCB8fCAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJ4XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0ID09IFwicnhcIiAmJiBvLnR5cGUgPT0gXCJyZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImN4XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8ucGF0dGVybiAmJiB1cGRhdGVQb3NpdGlvbihvKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImhlaWdodFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZGlydHkgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmZ5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0ID0gXCJ5XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBhdHRycy55O1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInlcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRycy5meSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gLWF0dHJzLnkgLSAoYXR0cnMuaGVpZ2h0IHx8IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicnlcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHQgPT0gXCJyeVwiICYmIG8udHlwZSA9PSBcInJlY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY3lcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgby5wYXR0ZXJuICYmIHVwZGF0ZVBvc2l0aW9uKG8pO1xuICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiclwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8udHlwZSA9PSBcInJlY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge3J4OiB2YWx1ZSwgcnk6IHZhbHVlfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic3JjXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoby50eXBlID09IFwiaW1hZ2VcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlTlMoeGxpbmssIFwiaHJlZlwiLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInN0cm9rZS13aWR0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8uXy5zeCAhPSAxIHx8IG8uXy
576015zeSAhPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgLz0gbW1heChhYnMoby5fLnN4KSwgYWJzKG8uXy5zeSkpIHx8IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyc1tcInN0cm9rZS1kYXNoYXJyYXlcIl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGREYXNoZXMobywgYXR0cnNbXCJzdHJva2UtZGFzaGFycmF5XCJdLCBwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG8uXy5hcnJvd3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInN0YXJ0U3RyaW5nXCIgaW4gby5fLmFycm93cyAmJiBhZGRBcnJvdyhvLCBvLl8uYXJyb3dzLnN0YXJ0U3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImVuZFN0cmluZ1wiIGluIG8uXy5hcnJvd3MgJiYgYWRkQXJyb3cobywgby5fLmFycm93cy5lbmRTdHJpbmcsIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzdHJva2UtZGFzaGFycmF5XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGREYXNoZXMobywgdmFsdWUsIHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImZpbGxcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpc1VSTCA9IFN0cih2YWx1ZSkubWF0Y2goUi5fSVNVUkwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVVJMKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwgPSAkKFwicGF0dGVyblwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgaWcgPSAkKFwiaW1hZ2VcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGVsLCB7eDogMCwgeTogMCwgcGF0dGVyblVuaXRzOiBcInVzZXJTcGFjZU9uVXNlXCIsIGhlaWdodDogMSwgd2lkdGg6IDF9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKGlnLCB7eDogMCwgeTogMCwgXCJ4bGluazpocmVmXCI6IGlzVVJMWzFdfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoaWcpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSLl9wcmVsb2FkKGlzVVJMWzFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdyA9IHRoaXMub2Zmc2V0V2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaCA9IHRoaXMub2Zmc2V0SGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChlbCwge3dpZHRoOiB3LCBoZWlnaHQ6IGh9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoaWcsIHt3aWR0aDogdywgaGVpZ2h0OiBofSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKGVsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhcGVyLmRlZnMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQobm9kZSwge2ZpbGw6IFwidXJsKCNcIiArIGVsLmlkICsgXCIpXCJ9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhdHRlcm4gPSBlbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvLnBhdHRlcm4gJiYgdXBkYXRlUG9zaXRpb24obyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgY2xyID0gUi5nZXRSR0IodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjbHIuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgcGFyYW1zLmdyYWRpZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBhdHRycy5ncmFkaWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhUi5pcyhhdHRycy5vcGFjaXR5LCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSLmlzKHBhcmFtcy5vcGFjaXR5LCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtvcGFjaXR5OiBhdHRycy5vcGFjaXR5fSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIVIuaXMoYXR0cnNbXCJmaWxsLW9wYWNpdHlcIl0sIFwidW5kZWZpbmVkXCIpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFIuaXMocGFyYW1zW1wiZmlsbC1vcGFjaXR5XCJdLCBcInVuZGVmaW5lZFwiKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcImZpbGwtb3BhY2l0eVwiOiBhdHRyc1tcImZpbGwtb3BhY2l0eVwiXX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoby50eXBlID09IFwiY2lyY2xlXCIgfHwgby50eXBlID09IFwiZWxsaXBzZVwiIHx8IFN0cih2YWx1ZSkuY2hhckF0KCkgIT0gXCJyXCIpICYmIGFkZEdyYWRpZW50RmlsbChvLCB2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXCJvcGFjaXR5XCIgaW4gYXR0cnMgfHwgXCJmaWxsLW9wYWNpdHlcIiBpbiBhdHRycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2Y
57601XIgZ3JhZGllbnQgPSBSLl9nLmRvYy5nZXRFbGVtZW50QnlJZChub2RlLmdldEF0dHJpYnV0ZShcImZpbGxcIikucmVwbGFjZSgvXnVybFxcKCN8XFwpJC9nLCBFKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChncmFkaWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0b3BzID0gZ3JhZGllbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdG9wXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJChzdG9wc1tzdG9wcy5sZW5ndGggLSAxXSwge1wic3RvcC1vcGFjaXR5XCI6IChcIm9wYWNpdHlcIiBpbiBhdHRycyA/IGF0dHJzLm9wYWNpdHkgOiAxKSAqIChcImZpbGwtb3BhY2l0eVwiIGluIGF0dHJzID8gYXR0cnNbXCJmaWxsLW9wYWNpdHlcIl0gOiAxKX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJzLmdyYWRpZW50ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0cnMuZmlsbCA9IFwibm9uZVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xyW2hhc10oXCJvcGFjaXR5XCIpICYmICQobm9kZSwge1wiZmlsbC1vcGFjaXR5XCI6IGNsci5vcGFjaXR5ID4gMSA/IGNsci5vcGFjaXR5IC8gMTAwIDogY2xyLm9wYWNpdHl9KTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInN0cm9rZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xyID0gUi5nZXRSR0IodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCBjbHIuaGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dCA9PSBcInN0cm9rZVwiICYmIGNscltoYXNdKFwib3BhY2l0eVwiKSAmJiAkKG5vZGUsIHtcInN0cm9rZS1vcGFjaXR5XCI6IGNsci5vcGFjaXR5ID4gMSA/IGNsci5vcGFjaXR5IC8gMTAwIDogY2xyLm9wYWNpdHl9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHQgPT0gXCJzdHJva2VcIiAmJiBvLl8uYXJyb3dzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJzdGFydFN0cmluZ1wiIGluIG8uXy5hcnJvd3MgJiYgYWRkQXJyb3cobywgby5fLmFycm93cy5zdGFydFN0cmluZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJlbmRTdHJpbmdcIiBpbiBvLl8uYXJyb3dzICYmIGFkZEFycm93KG8sIG8uXy5hcnJvd3MuZW5kU3RyaW5nLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZ3JhZGllbnRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIChvLnR5cGUgPT0gXCJjaXJjbGVcIiB8fCBvLnR5cGUgPT0gXCJlbGxpcHNlXCIgfHwgU3RyKHZhbHVlKS5jaGFyQXQoKSAhPSBcInJcIikgJiYgYWRkR3JhZGllbnRGaWxsKG8sIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwib3BhY2l0eVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmdyYWRpZW50ICYmICFhdHRyc1toYXNdKFwic3Ryb2tlLW9wYWNpdHlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKG5vZGUsIHtcInN0cm9rZS1vcGFjaXR5XCI6IHZhbHVlID4gMSA/IHZhbHVlIC8gMTAwIDogdmFsdWV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhbGxcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImZpbGwtb3BhY2l0eVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJzLmdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQgPSBSLl9nLmRvYy5nZXRFbGVtZW50QnlJZChub2RlLmdldEF0dHJpYnV0ZShcImZpbGxcIikucmVwbGFjZSgvXnVybFxcKCN8XFwpJC9nLCBFKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3BzID0gZ3JhZGllbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdG9wXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkKHN0b3BzW3N0b3BzLmxlbmd0aCAtIDFdLCB7XCJzdG9wLW9wYWNpdHlcIjogdmFsdWV9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBhdHQgPT0gXCJmb250LXNpemVcIiAmJiAodmFsdWUgPSB0b0ludCh2YWx1ZSwgMTApICsgXCJweFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjc3NydWxlID0gYXR0LnJlcGxhY2UoLyhcXC0uKS9nLCBmdW5jdGlvbiAodykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3LnN1YnN0cmluZygxKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2Nzc3J1bGVdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZGlydHkgPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0dW5lVGV4dChvLCBwYXJhbXMpO1xuICAgICAgICBub2RlLnN0eWxlLnZpc2liaWxpdHkgPSB2aXM7XG4gICAgfSxcbiAgICBsZWFkaW5nID0gMS4yLFxuICAgIHR1bmVUZXh0ID0gZnVuY3Rpb24gKGVsLCBwYXJhbXMpIHtcbiAgICAgICAgaWYgKGVsLnR5cGUgIT0gXCJ0ZXh0XCIgfHwgIShwYXJhbXNbaGFzXShcInRleHRcIikgfHwgcGFyYW1zW2hhc10oXCJmb250XCIpIHx8IHBhcmFtc1toYXNdKFwiZm9udC1zaXplXCIpIHx8IHBhcmFtc1toYXNdKFwieFwiKSB8fCBwYXJhbXNbaGFzXShcInlcIikpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgI
57601H1cbiAgICAgICAgdmFyIGEgPSBlbC5hdHRycyxcbiAgICAgICAgICAgIG5vZGUgPSBlbC5ub2RlLFxuICAgICAgICAgICAgZm9udFNpemUgPSBub2RlLmZpcnN0Q2hpbGQgPyB0b0ludChSLl9nLmRvYy5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKG5vZGUuZmlyc3RDaGlsZCwgRSkuZ2V0UHJvcGVydHlWYWx1ZShcImZvbnQtc2l6ZVwiKSwgMTApIDogMTA7XG5cbiAgICAgICAgaWYgKHBhcmFtc1toYXNdKFwidGV4dFwiKSkge1xuICAgICAgICAgICAgYS50ZXh0ID0gcGFyYW1zLnRleHQ7XG4gICAgICAgICAgICB3aGlsZSAobm9kZS5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVDaGlsZChub2RlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRleHRzID0gU3RyKHBhcmFtcy50ZXh0KS5zcGxpdChcIlxcblwiKSxcbiAgICAgICAgICAgICAgICB0c3BhbnMgPSBbXSxcbiAgICAgICAgICAgICAgICB0c3BhbjtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRleHRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0c3BhbiA9ICQoXCJ0c3BhblwiKTtcbiAgICAgICAgICAgICAgICBpICYmICQodHNwYW4sIHtkeTogZm9udFNpemUgKiBsZWFkaW5nLCB4OiBhLnh9KTtcbiAgICAgICAgICAgICAgICB0c3Bhbi5hcHBlbmRDaGlsZChSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZSh0ZXh0c1tpXSkpO1xuICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQodHNwYW4pO1xuICAgICAgICAgICAgICAgIHRzcGFuc1tpXSA9IHRzcGFuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHNwYW5zID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShcInRzcGFuXCIpO1xuICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSB0c3BhbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgaWYgKGkpIHtcbiAgICAgICAgICAgICAgICAkKHRzcGFuc1tpXSwge2R5OiBmb250U2l6ZSAqIGxlYWRpbmcsIHg6IGEueH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKHRzcGFuc1swXSwge2R5OiAwfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgJChub2RlLCB7eDogYS54LCB5OiBhLnl9KTtcbiAgICAgICAgZWwuXy5kaXJ0eSA9IDE7XG4gICAgICAgIHZhciBiYiA9IGVsLl9nZXRCQm94KCksXG4gICAgICAgICAgICBkaWYgPSBhLnkgLSAoYmIueSArIGJiLmhlaWdodCAvIDIpO1xuICAgICAgICBkaWYgJiYgUi5pcyhkaWYsIFwiZmluaXRlXCIpICYmICQodHNwYW5zWzBdLCB7ZHk6IGRpZn0pO1xuICAgIH0sXG4gICAgZ2V0UmVhbE5vZGUgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlICYmIG5vZGUucGFyZW50Tm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiYVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZS5wYXJlbnROb2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIEVsZW1lbnQgPSBmdW5jdGlvbiAobm9kZSwgc3ZnKSB7XG4gICAgICAgIHZhciBYID0gMCxcbiAgICAgICAgICAgIFkgPSAwO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQubm9kZVxuICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBHaXZlcyB5b3UgYSByZWZlcmVuY2UgdG8gdGhlIERPTSBvYmplY3QsIHNvIHlvdSBjYW4gYXNzaWduIGV2ZW50IGhhbmRsZXJzIG9yIGp1c3QgbWVzcyBhcm91bmQuXG4gICAgICAgICAqKlxuICAgICAgICAgKiBOb3RlOiBEb27igJl0IG1lc3Mgd2l0aCBpdC5cbiAgICAgICAgID4gVXNhZ2VcbiAgICAgICAgIHwgLy8gZHJhdyBhIGNpcmNsZSBhdCBjb29yZGluYXRlIDEwLDEwIHdpdGggcmFkaXVzIG9mIDEwXG4gICAgICAgICB8IHZhciBjID0gcGFwZXIuY2lyY2xlKDEwLCAxMCwgMTApO1xuICAgICAgICAgfCBjLm5vZGUub25jbGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgIHwgICAgIGMuYXR0cihcImZpbGxcIiwgXCJyZWRcIik7XG4gICAgICAgICB8IH07XG4gICAgICAgIFxcKi9cbiAgICAgICAgdGhpc1swXSA9IHRoaXMubm9kZSA9IG5vZGU7XG4gICAgICAgIC8qXFxcbiAgICAgICAgICogRWxlbWVudC5yYXBoYWVsXG4gICAgICAgICBbIHByb3BlcnR5IChvYmplY3QpIF1cbiAgICAgICAgICoqXG4gICAgICAgICAqIEludGVybmFsIHJlZmVyZW5jZSB0byBAUmFwaGFlbCBvYmplY3QuIEluIGNhc2UgaXQgaXMgbm90IGF2YWlsYWJsZS5cbiAgICAgICAgID4gVXNhZ2VcbiAgICAgICAgIHwgUmFwaGFlbC5lbC5yZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICB8ICAgICB2YXIgaHNiID0gdGhpcy5wYXBlci
576015yYXBoYWVsLnJnYjJoc2IodGhpcy5hdHRyKFwiZmlsbFwiKSk7XG4gICAgICAgICB8ICAgICBoc2IuaCA9IDE7XG4gICAgICAgICB8ICAgICB0aGlzLmF0dHIoe2ZpbGw6IHRoaXMucGFwZXIucmFwaGFlbC5oc2IycmdiKGhzYikuaGV4fSk7XG4gICAgICAgICB8IH1cbiAgICAgICAgXFwqL1xuICAgICAgICBub2RlLnJhcGhhZWwgPSB0cnVlO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQuaWRcbiAgICAgICAgIFsgcHJvcGVydHkgKG51bWJlcikgXVxuICAgICAgICAgKipcbiAgICAgICAgICogVW5pcXVlIGlkIG9mIHRoZSBlbGVtZW50LiBFc3BlY2lhbGx5IHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIGxpc3RlbiB0byBldmVudHMgb2YgdGhlIGVsZW1lbnQsXG4gICAgICAgICAqIGJlY2F1c2UgYWxsIGV2ZW50cyBhcmUgZmlyZWQgaW4gZm9ybWF0IGA8bW9kdWxlPi48YWN0aW9uPi48aWQ+YC4gQWxzbyB1c2VmdWwgZm9yIEBQYXBlci5nZXRCeUlkIG1ldGhvZC5cbiAgICAgICAgXFwqL1xuICAgICAgICB0aGlzLmlkID0gZ3VpZCgpO1xuICAgICAgICBub2RlLnJhcGhhZWxpZCA9IHRoaXMuaWQ7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICogTWV0aG9kIHRoYXQgcmV0dXJucyBhIDUgbGV0dGVyL2RpZ2l0IGlkLCBlbm91Z2ggZm9yIDM2XjUgPSA2MDQ2NjE3NiBlbGVtZW50c1xuICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IGlkXG4gICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGd1aWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gKFwiMDAwMFwiICsgKE1hdGgucmFuZG9tKCkqTWF0aC5wb3coMzYsNSkgPDwgMCkudG9TdHJpbmcoMzYpKS5zbGljZSgtNSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1hdHJpeCA9IFIubWF0cml4KCk7XG4gICAgICAgIHRoaXMucmVhbFBhdGggPSBudWxsO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQucGFwZXJcbiAgICAgICAgIFsgcHJvcGVydHkgKG9iamVjdCkgXVxuICAgICAgICAgKipcbiAgICAgICAgICogSW50ZXJuYWwgcmVmZXJlbmNlIHRvIOKAnHBhcGVy4oCdIHdoZXJlIG9iamVjdCBkcmF3bi4gTWFpbmx5IGZvciB1c2UgaW4gcGx1Z2lucyBhbmQgZWxlbWVudCBleHRlbnNpb25zLlxuICAgICAgICAgPiBVc2FnZVxuICAgICAgICAgfCBSYXBoYWVsLmVsLmNyb3NzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgfCAgICAgdGhpcy5hdHRyKHtmaWxsOiBcInJlZFwifSk7XG4gICAgICAgICB8ICAgICB0aGlzLnBhcGVyLnBhdGgoXCJNMTAsMTBMNTAsNTBNNTAsMTBMMTAsNTBcIilcbiAgICAgICAgIHwgICAgICAgICAuYXR0cih7c3Ryb2tlOiBcInJlZFwifSk7XG4gICAgICAgICB8IH1cbiAgICAgICAgXFwqL1xuICAgICAgICB0aGlzLnBhcGVyID0gc3ZnO1xuICAgICAgICB0aGlzLmF0dHJzID0gdGhpcy5hdHRycyB8fCB7fTtcbiAgICAgICAgdGhpcy5fID0ge1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBbXSxcbiAgICAgICAgICAgIHN4OiAxLFxuICAgICAgICAgICAgc3k6IDEsXG4gICAgICAgICAgICBkZWc6IDAsXG4gICAgICAgICAgICBkeDogMCxcbiAgICAgICAgICAgIGR5OiAwLFxuICAgICAgICAgICAgZGlydHk6IDFcbiAgICAgICAgfTtcbiAgICAgICAgIXN2Zy5ib3R0b20gJiYgKHN2Zy5ib3R0b20gPSB0aGlzKTtcbiAgICAgICAgLypcXFxuICAgICAgICAgKiBFbGVtZW50LnByZXZcbiAgICAgICAgIFsgcHJvcGVydHkgKG9iamVjdCkgXVxuICAgICAgICAgKipcbiAgICAgICAgICogUmVmZXJlbmNlIHRvIHRoZSBwcmV2aW91cyBlbGVtZW50IGluIHRoZSBoaWVyYXJjaHkuXG4gICAgICAgIFxcKi9cbiAgICAgICAgdGhpcy5wcmV2ID0gc3ZnLnRvcDtcbiAgICAgICAgc3ZnLnRvcCAmJiAoc3ZnLnRvcC5uZXh0ID0gdGhpcyk7XG4gICAgICAgIHN2Zy50b3AgPSB0aGlzO1xuICAgICAgICAvKlxcXG4gICAgICAgICAqIEVsZW1lbnQubmV4dFxuICAgICAgICAgWyBwcm9wZXJ0eSAob2JqZWN0KSBdXG4gICAgICAgICAqKlxuICAgICAgICAgKiBSZWZlcmVuY2UgdG8gdGhlIG5leHQgZWxlbWVudCBpbiB0aGUgaGllcmFyY2h5LlxuICAgICAgICBcXCovXG4gICAgICAgIHRoaXMubmV4dCA9IG51bGw7XG4gICAgfSxcbiAgICBlbHByb3RvID0gUi5lbDtcblxuICAgIEVsZW1lbnQucHJvdG90eXBlID0gZWxwcm90bztcbiAgICBlbHByb3RvLmNvbnN0cnVjdG9yID0gRWxlbWVudDtcblxuICAgIFIuX2VuZ2luZS5wYXRoID0gZnVuY3Rpb24gKHBhdGhTdHJpbmcsIFNWRykge1xuICAgICAgICB2Y
57601XIgZWwgPSAkKFwicGF0aFwiKTtcbiAgICAgICAgU1ZHLmNhbnZhcyAmJiBTVkcuY2FudmFzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgdmFyIHAgPSBuZXcgRWxlbWVudChlbCwgU1ZHKTtcbiAgICAgICAgcC50eXBlID0gXCJwYXRoXCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocCwge1xuICAgICAgICAgICAgZmlsbDogXCJub25lXCIsXG4gICAgICAgICAgICBzdHJva2U6IFwiIzAwMFwiLFxuICAgICAgICAgICAgcGF0aDogcGF0aFN0cmluZ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5yb3RhdGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERlcHJlY2F0ZWQhIFVzZSBARWxlbWVudC50cmFuc2Zvcm0gaW5zdGVhZC5cbiAgICAgKiBBZGRzIHJvdGF0aW9uIGJ5IGdpdmVuIGFuZ2xlIGFyb3VuZCBnaXZlbiBwb2ludCB0byB0aGUgbGlzdCBvZlxuICAgICAqIHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gZGVnIChudW1iZXIpIGFuZ2xlIGluIGRlZ3JlZXNcbiAgICAgLSBjeCAobnVtYmVyKSAjb3B0aW9uYWwgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygcm90YXRpb25cbiAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWwgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygcm90YXRpb25cbiAgICAgKiBJZiBjeCAmIGN5IGFyZW7igJl0IHNwZWNpZmllZCBjZW50cmUgb2YgdGhlIHNoYXBlIGlzIHVzZWQgYXMgYSBwb2ludCBvZiByb3RhdGlvbi5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJvdGF0ZSA9IGZ1bmN0aW9uIChkZWcsIGN4LCBjeSkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBkZWcgPSBTdHIoZGVnKS5zcGxpdChzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoZGVnLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIGN4ID0gdG9GbG9hdChkZWdbMV0pO1xuICAgICAgICAgICAgY3kgPSB0b0Zsb2F0KGRlZ1syXSk7XG4gICAgICAgIH1cbiAgICAgICAgZGVnID0gdG9GbG9hdChkZWdbMF0pO1xuICAgICAgICAoY3kgPT0gbnVsbCkgJiYgKGN4ID0gY3kpO1xuICAgICAgICBpZiAoY3ggPT0gbnVsbCB8fCBjeSA9PSBudWxsKSB7XG4gICAgICAgICAgICB2Y
57601XIgYmJveCA9IHRoaXMuZ2V0QkJveCgxKTtcbiAgICAgICAgICAgIGN4ID0gYmJveC54ICsgYmJveC53aWR0aCAvIDI7XG4gICAgICAgICAgICBjeSA9IGJib3gueSArIGJib3guaGVpZ2h0IC8gMjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1wiclwiLCBkZWcsIGN4LCBjeV1dKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuc2NhbGVcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIERlcHJlY2F0ZWQhIFVzZSBARWxlbWVudC50cmFuc2Zvcm0gaW5zdGVhZC5cbiAgICAgKiBBZGRzIHNjYWxlIGJ5IGdpdmVuIGFtb3VudCByZWxhdGl2ZSB0byBnaXZlbiBwb2ludCB0byB0aGUgbGlzdCBvZlxuICAgICAqIHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gc3ggKG51bWJlcikgaG9yaXNvbnRhbCBzY2FsZSBhbW91bnRcbiAgICAgLSBzeSAobnVtYmVyKSB2ZXJ0aWNhbCBzY2FsZSBhbW91bnRcbiAgICAgLSBjeCAobnVtYmVyKSAjb3B0aW9uYWwgeCBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygc2NhbGVcbiAgICAgLSBjeSAobnVtYmVyKSAjb3B0aW9uYWwgeSBjb29yZGluYXRlIG9mIHRoZSBjZW50cmUgb2Ygc2NhbGVcbiAgICAgKiBJZiBjeCAmIGN5IGFyZW7igJl0IHNwZWNpZmllZCBjZW50cmUgb2YgdGhlIHNoYXBlIGlzIHVzZWQgaW5zdGVhZC5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnNjYWxlID0gZnVuY3Rpb24gKHN4LCBzeSwgY3gsIGN5KSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHN4ID0gU3RyKHN4KS5zcGxpdChzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoc3gubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgc3kgPSB0b0Zsb2F0KHN4WzFdKTtcbiAgICAgICAgICAgIGN4ID0gdG9GbG9hdChzeFsyXSk7XG4gICAgICAgICAgICBjeSA9IHRvRmxvYXQoc3hbM10pO1xuICAgICAgICB9XG4gICAgICAgIHN4ID0gdG9GbG9hdChzeFswXSk7XG4gICAgICAgIChzeSA9PSBudWxsKSAmJiAoc3kgPSBzeCk7XG4gICAgICAgIChjeSA9PSBudWxsKSAmJiAoY3ggPSBjeSk7XG4gICAgICAgIGlmIChjeCA9PSBudWxsIHx8IGN5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBiYm94ID0gdGhpcy5nZXRCQm94KDEpO1xuICAgICAgICB9XG4gICAgICAgIGN4ID0gY3ggPT0gbnVsbCA/IGJib3gueCArIGJib3gud2lkdGggLyAyIDogY3g7XG4gICAgICAgIGN5ID0gY3kgPT0gbnVsbCA/IGJib3gueSArIGJib3guaGVpZ2h0IC8gMiA6IGN5O1xuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1wic1wiLCBzeCwgc3ksIGN4LCBjeV1dKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQudHJhbnNsYXRlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBEZXByZWNhdGVkISBVc2UgQEVsZW1lbnQudHJhbnNmb3JtIGluc3RlYWQuXG4gICAgICogQWRkcyB0cmFuc2xhdGlvbiBieSBnaXZlbiBhbW91bnQgdG8gdGhlIGxpc3Qgb2YgdHJhbnNmb3JtYXRpb25zIG9mIHRoZSBlbGVtZW50LlxuICAgICA+IFBhcmFtZXRlcnNcbiAgICAgLSBkeCAobnVtYmVyKSBob3Jpc29udGFsIHNoaWZ0XG4gICAgIC0gZHkgKG51bWJlcikgdmVydGljYWwgc2hpZnRcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChkeCwgZHkpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZHggPSBTdHIoZHgpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChkeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBkeSA9IHRvRmxvYXQoZHhbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGR4ID0gdG9GbG9hdChkeFswXSkgfHwgMDtcbiAgICAgICAgZHkgPSArZHkgfHwgMDtcbiAgICAgICAgdGhpcy50cmFuc2Zvcm0odGhpcy5fLnRyYW5zZm9ybS5jb25jYXQoW1tcInRcIiwgZHgsIGR5XV0pKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC50cmFuc2Zvcm1cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEFkZHMgdHJhbnNmb3JtYXRpb24gdG8gdGhlIGVsZW1lbnQgd2hpY2ggaXMgc2VwYXJhdGUgdG8gb3RoZXIgYXR0cmlidXRlcyxcbiAgICAgKiBpLmUuIHRyYW5zbGF0aW9uIGRvZXNu4oCZdCBjaGFuZ2UgYHhgIG9yIGB5YCBvZiB0aGUgcmVjdGFuZ2UuIFRoZSBmb3JtYXRcbiAgICAgKiBvZiB0cmFuc2Zvcm1hdGlvbiBzdHJpbmcgaXMgc2ltaWxhciB0byB0aGUgcGF0aCBzdHJpbmcgc3ludGF4OlxuICAgICB8IFwidDEwMCwxMDByMzAsMTAwLDEwMHMyLDIsMTAwLDEwMHI0NXMxLjVcIlxuICAgICAqIEVhY2ggbGV0dGVyIGlzIGEgY29tbWFuZC4gVGhlcmUgYXJlIGZvdXIgY29tbWFuZHM6IGB0YCBpcyBmb3IgdHJhbnNsYXRlLCBgcmAgaXMgZm9yIHJvdGF0ZSwgYHNgIGlzIGZvclxuICAgICAqIHNjYWxlIGFuZCBgbWAgaXMgZm9yIG1hdHJpeC5cbiAgICAgKlxuICAgICAqIFRoZXJlIGFyZSBhbHNvIGFsdGVybmF0aXZlIOKAnGFic29sdXRl4oCdIHRyYW5zbGF0aW9uLCByb3RhdGlvbiBhbmQgc2NhbGU6IGBUYCwgYFJgIGFuZCBgU2AuIFRoZXkgd2lsbCBub3QgdGFrZSBwcmV2aW91cyB0cmFuc2Zvcm1hdGlvbiBpbnRvIGFjY291bnQuIEZvciBleGFtcGxlLCBgLi4uVDEwMCwwYCB3aWxsIGFsd2F5cyBtb3ZlIGVsZW1lbnQgMTAwIHB4IGhvcmlzb250YWxseSwgd2hpbGUgYC4uLnQxMDAsMGAgY291bGQgbW92ZSBpdCB2ZXJ0aWNhbGx5IGlmIHRoZXJlIGlzIGByOTBgIGJlZm9yZS4gSnVzdCBjb21wYXJlIHJlc3VsdHMgb2YgYHI5MHQxMDAsMGAgYW5kIGByOTBUMTAwLDBgLlxuICAgICAqXG4gICAgICogU28sIHRoZSBleGFtcGxlIGxpbmUgYWJvdmUgY291bGQgYmUgcmVhZCBsaWtlIOKAnHRyYW5zbGF0ZSBieSAxMDAsIDEwMDsgcm90YXRlIDMwwrAgYXJvdW5kIDEwMCwgMTAwOyBzY2FsZSB0d2ljZSBhcm91bmQgMTAwLCAxMDA7XG4gICAgICogcm90YXRlIDQ1wrAgYXJvdW5kIGNlbnRyZTsgc2NhbGUgMS41IHRpbWVzIHJlbGF0aXZlIHRvIGNlbnRyZeKAnS4gQXMgeW91IGNhbiBzZWUgcm90YXRlIGFuZCBzY2FsZSBjb21tYW5kcyBoYXZlIG9yaWdpblxuICAgICAqIGNvb3JkaW5hdGVzIGFzIG9wdGlvbmFsIHBhcmFtZXRlcnMsIHRoZSBkZWZhdWx0IGlzIHRoZSBjZW50cmUgcG9pbnQgb2YgdGhlIGVsZW1lbnQuXG4gICAgICogTWF0cml4IGFjY2VwdHMgc2l4IHBhcmFtZXRlcnMuXG4gICAgID4gVXNhZ2
57601VcbiAgICAgfCB2YXIgZWwgPSBwYXBlci5yZWN0KDEwLCAyMCwgMzAwLCAyMDApO1xuICAgICB8IC8vIHRyYW5zbGF0ZSAxMDAsIDEwMCwgcm90YXRlIDQ1wrAsIHRyYW5zbGF0ZSAtMTAwLCAwXG4gICAgIHwgZWwudHJhbnNmb3JtKFwidDEwMCwxMDByNDV0LTEwMCwwXCIpO1xuICAgICB8IC8vIGlmIHlvdSB3YW50IHlvdSBjYW4gYXBwZW5kIG9yIHByZXBlbmQgdHJhbnNmb3JtYXRpb25zXG4gICAgIHwgZWwudHJhbnNmb3JtKFwiLi4udDUwLDUwXCIpO1xuICAgICB8IGVsLnRyYW5zZm9ybShcInMyLi4uXCIpO1xuICAgICB8IC8vIG9yIGV2ZW4gd3JhcFxuICAgICB8IGVsLnRyYW5zZm9ybShcInQ1MCw1MC4uLnQtNTAtNTBcIik7XG4gICAgIHwgLy8gdG8gcmVzZXQgdHJhbnNmb3JtYXRpb24gY2FsbCBtZXRob2Qgd2l0aCBlbXB0eSBzdHJpbmdcbiAgICAgfCBlbC50cmFuc2Zvcm0oXCJcIik7XG4gICAgIHwgLy8gdG8gZ2V0IGN1cnJlbnQgdmFsdWUgY2FsbCBpdCB3aXRob3V0IHBhcmFtZXRlcnNcbiAgICAgfCBjb25zb2xlLmxvZyhlbC50cmFuc2Zvcm0oKSk7XG4gICAgID4gUGFyYW1ldGVyc1xuICAgICAtIHRzdHIgKHN0cmluZykgI29wdGlvbmFsIHRyYW5zZm9ybWF0aW9uIHN0cmluZ1xuICAgICAqIElmIHRzdHIgaXNu4oCZdCBzcGVjaWZpZWRcbiAgICAgPSAoc3RyaW5nKSBjdXJyZW50IHRyYW5zZm9ybWF0aW9uIHN0cmluZ1xuICAgICAqIGVsc2VcbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0c3RyKSB7XG4gICAgICAgIHZhciBfID0gdGhpcy5fO1xuICAgICAgICBpZiAodHN0ciA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gXy50cmFuc2Zvcm07XG4gICAgICAgIH1cbiAgICAgICAgUi5fZXh0cmFjdFRyYW5zZm9ybSh0aGlzLCB0c3RyKTtcblxuICAgICAgICB0aGlzLmNsaXAgJiYgJCh0aGlzLmNsaXAsIHt0cmFuc2Zvcm06IHRoaXMubWF0cml4LmludmVydCgpfSk7XG4gICAgICAgIHRoaXMucGF0dGVybiAmJiB1cGRhdGVQb3NpdGlvbih0aGlzKTtcbiAgICAgICAgdGhpcy5ub2RlICYmICQodGhpcy5ub2RlLCB7dHJhbnNmb3JtOiB0aGlzLm1hdHJpeH0pO1xuXG4gICAgICAgIGlmIChfLnN4ICE9IDEgfHwgXy5zeSAhPSAxKSB7XG4gICAgICAgICAgICB2Y
57601XIgc3cgPSB0aGlzLmF0dHJzW2hhc10oXCJzdHJva2Utd2lkdGhcIikgPyB0aGlzLmF0dHJzW1wic3Ryb2tlLXdpZHRoXCJdIDogMTtcbiAgICAgICAgICAgIHRoaXMuYXR0cih7XCJzdHJva2Utd2lkdGhcIjogc3d9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaGlkZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogTWFrZXMgZWxlbWVudCBpbnZpc2libGUuIFNlZSBARWxlbWVudC5zaG93LlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYoIXRoaXMucmVtb3ZlZCkgdGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5zaG93XG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBNYWtlcyBlbGVtZW50IHZpc2libGUuIFNlZSBARWxlbWVudC5oaWRlLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYoIXRoaXMucmVtb3ZlZCkgdGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnJlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyBlbGVtZW50IGZyb20gdGhlIHBhcGVyLlxuICAgIFxcKi9cbiAgICBlbHByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vZGUgPSBnZXRSZWFsTm9kZSh0aGlzLm5vZGUpO1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkIHx8ICFub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2Y
57601XIgcGFwZXIgPSB0aGlzLnBhcGVyO1xuICAgICAgICBwYXBlci5fX3NldF9fICYmIHBhcGVyLl9fc2V0X18uZXhjbHVkZSh0aGlzKTtcbiAgICAgICAgZXZlLnVuYmluZChcInJhcGhhZWwuKi4qLlwiICsgdGhpcy5pZCk7XG4gICAgICAgIGlmICh0aGlzLmdyYWRpZW50KSB7XG4gICAgICAgICAgICBwYXBlci5kZWZzLnJlbW92ZUNoaWxkKHRoaXMuZ3JhZGllbnQpO1xuICAgICAgICB9XG4gICAgICAgIFIuX3RlYXIodGhpcywgcGFwZXIpO1xuXG4gICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcblxuICAgICAgICAvLyBSZW1vdmUgY3VzdG9tIGRhdGEgZm9yIGVsZW1lbnRcbiAgICAgICAgdGhpcy5yZW1vdmVEYXRhKCk7XG5cbiAgICAgICAgZm9yICh2YXIgaSBpbiB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzW2ldID0gdHlwZW9mIHRoaXNbaV0gPT0gXCJmdW5jdGlvblwiID8gUi5fcmVtb3ZlZEZhY3RvcnkoaSkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlZCA9IHRydWU7XG4gICAgfTtcbiAgICBlbHByb3RvLl9nZXRCQm94ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPT0gXCJub25lXCIpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgICAgICAgdmFyIGhpZGUgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjYW52YXNIaWRkZW4gPSBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRhaW5lclN0eWxlO1xuICAgICAgICBpZiAodGhpcy5wYXBlci
576015jYW52YXMucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgIGNvbnRhaW5lclN0eWxlID0gdGhpcy5wYXBlci5jYW52YXMucGFyZW50RWxlbWVudC5zdHlsZTtcbiAgICAgICAgfSAvL0lFMTArIGNhbid0IGZpbmQgcGFyZW50RWxlbWVudFxuICAgICAgICBlbHNlIGlmICh0aGlzLnBhcGVyLmNhbnZhcy5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgY29udGFpbmVyU3R5bGUgPSB0aGlzLnBhcGVyLmNhbnZhcy5wYXJlbnROb2RlLnN0eWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY29udGFpbmVyU3R5bGUgJiYgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9PSBcIm5vbmVcIikge1xuICAgICAgICAgIGNhbnZhc0hpZGRlbiA9IHRydWU7XG4gICAgICAgICAgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9IFwiXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJib3ggPSB7fTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGJib3ggPSB0aGlzLm5vZGUuZ2V0QkJveCgpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIC8vIEZpcmVmb3ggMy4wLngsIDI1LjAuMSAocHJvYmFibHkgbW9yZSB2ZXJzaW9ucyBhZmZlY3RlZCkgcGxheSBiYWRseSBoZXJlIC0gcG9zc2libGUgZml4XG4gICAgICAgICAgICBiYm94ID0ge1xuICAgICAgICAgICAgICAgIHg6IHRoaXMubm9kZS5jbGllbnRMZWZ0LFxuICAgICAgICAgICAgICAgIHk6IHRoaXMubm9kZS5jbGllbnRUb3AsXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMubm9kZS5jbGllbnRXaWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMubm9kZS5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIGJib3ggPSBiYm94IHx8IHt9O1xuICAgICAgICAgICAgaWYoY2FudmFzSGlkZGVuKXtcbiAgICAgICAgICAgICAgY29udGFpbmVyU3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGhpZGUgJiYgdGhpcy5oaWRlKCk7XG4gICAgICAgIHJldHVybiBiYm94O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuYXR0clxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogU2V0cyB0aGUgYXR0cmlidXRlcyBvZiB0aGUgZWxlbWVudC5cbiAgICAgPiBQYXJhbWV0ZXJzXG4gICAgIC0gYXR0ck5hbWUgKHN0cmluZykgYXR0cmlidXRl4oCZcyBuYW1lXG4gICAgIC0gdmFsdWUgKHN0cmluZykgdmFsdWVcbiAgICAgKiBvclxuICAgICAtIHBhcmFtcyAob2JqZWN0KSBvYmplY3Qgb2YgbmFtZS92YWx1ZSBwYWlyc1xuICAgICAqIG9yXG4gICAgIC0gYXR0ck5hbWUgKHN0cmluZykgYXR0cmlidXRl4oCZcyBuYW1lXG4gICAgICogb3JcbiAgICAgLSBhdHRyTmFtZXMgKGFycmF5KSBpbiB0aGlzIGNhc2UgbWV0aG9kIHJldHVybnMgYXJyYXkgb2YgY3VycmVudCB2YWx1ZXMgZm9yIGdpdmVuIGF0dHJpYnV0ZSBuYW1lc1xuICAgICA9IChvYmplY3QpIEBFbGVtZW50IGlmIGF0dHJzTmFtZSAmIHZhbHVlIG9yIHBhcmFtcyBhcmUgcGFzc2VkIGluLlxuICAgICA9ICguLi4pIHZhbHVlIG9mIHRoZSBhdHRyaWJ1dGUgaWYgb25seSBhdHRyc05hbWUgaXMgcGFzc2VkIGluLlxuICAgICA9IChhcnJheSkgYXJyYXkgb2YgdmFsdWVzIG9mIHRoZSBhdHRyaWJ1dGUgaWYgYXR0cnNOYW1lcyBpcyBwYXNzZWQgaW4uXG4gICAgID0gKG9iamVjdCkgb2JqZWN0IG9mIGF0dHJpYnV0ZXMgaWYgbm90aGluZyBpcyBwYXNzZWQgaW4uXG4gICAgID4gUG9zc2libGUgcGFyYW1ldGVyc1xuICAgICAjIDxwPlBsZWFzZSByZWZlciB0byB0aGUgPGEgaHJlZj1cImh0dHA6Ly93d3cudzMub3JnL1RSL1NWRy9cIiB0aXRsZT1cIlRoZSBXM0MgUmVjb21tZW5kYXRpb24gZm9yIHRoZSBTVkcgbGFuZ3VhZ2UgZGVzY3JpYmVzIHRoZXNlIHByb3BlcnRpZXMgaW4gZGV0YWlsLlwiPlNWRyBzcGVjaWZpY2F0aW9uPC9hPiBmb3IgYW4gZXhwbGFuYXRpb24gb2YgdGhlc2UgcGFyYW1ldGVycy48L3A+XG4gICAgIG8gYXJyb3ctZW5kIChzdHJpbmcpIGFycm93aGVhZCBvbiB0aGUgZW5kIG9mIHRoZSBwYXRoLiBUaGUgZm9ybWF0IGZvciBzdHJpbmcgaXMgYDx0eXBlPlstPHdpZHRoPlstPGxlbmd0aD5dXWAuIFBvc3NpYmxlIHR5cGVzOiBgY2xhc3NpY2AsIGBibG9ja2AsIGBvcGVuYCwgYG92YWxgLCBgZGlhbW9uZGAsIGBub25lYCwgd2lkdGg6IGB3aWRlYCwgYG5hcnJvd2AsIGBtZWRpdW1gLCBsZW5ndGg6IGBsb25nYCwgYHNob3J0YCwgYG1pZGl1bWAuXG4gICAgIG8gY2xpcC1yZWN0IChzdHJpbmcpIGNvbW1hIG9yIHNwYWNlIHNlcGFyYXRlZCB2YWx1ZXM6IHgsIHksIHdpZHRoIGFuZCBoZWlnaHRcbiAgICAgbyBjdXJzb3IgKHN0cmluZykgQ1NTIHR5cGUgb2YgdGhlIGN1cnNvclxuICAgICBvIGN4IChudW1iZXIpIHRoZSB4LWF4aXMgY29vcmRpbmF0ZSBvZiB0aGUgY2VudGVyIG9mIHRoZSBjaXJjbGUsIG9yIGVsbGlwc2VcbiAgICAgbyBjeSAobnVtYmVyKSB0aGUgeS1heGlzIGNvb3JkaW5hdGUgb2YgdGhlIGNlbnRlciBvZiB0aGUgY2lyY2xlLCBvciBlbGxpcHNlXG4gICAgIG8gZmlsbCAoc3RyaW5nKSBjb2xvdXIsIGdyYWRpZW50IG9yIGltYWdlXG4gICAgIG8gZmlsbC1vcGFjaXR5IChudW1iZXIpXG4gICAgIG8gZm9udCAoc3RyaW5nKVxuICAgICBvIGZvbnQtZmFtaWx5IChzdHJpbmcpXG4gICAgIG8gZm9udC1zaXplIChudW1iZXIpIGZvbnQgc2l6ZSBpbiBwaXhlbHNcbiAgICAgbyBmb250LXdlaWdodCAoc3RyaW5nKVxuICAgICBvIGhlaWdodCAobnVtYmVyKVxuICAgICBvIGhyZWYgKHN0cmluZykgVVJMLCBpZiBzcGVjaWZpZWQgZWxlbWVudCBiZWhhdmVzIGFzIGh5cGVybGlua1xuICAgICBvIG9wYWNpdHkgKG51bWJlcilcbiAgICAgbyBwYXRoIChzdHJpbmcpIFNWRyBwYXRoIHN0cmluZyBmb3JtYXRcbiAgICAgbyByIChudW1iZXIpIHJhZGl1cyBvZiB0aGUgY2lyY2xlLCBlbGxpcHNlIG9yIHJvdW5kZWQgY29ybmVyIG9uIHRoZSByZWN0XG4gICAgIG8gcnggKG51bWJlcikgaG9yaXNvbnRhbCByYWRpdXMgb2YgdGhlIGVsbGlwc2VcbiAgICAgbyByeSAobnVtYmVyKSB2ZXJ0aWNhbCByYWRpdXMgb2YgdGhlIGVsbGlwc2VcbiAgICAgbyBzcmMgKHN0cmluZykgaW1hZ2UgVVJMLCBvbmx5IHdvcmtzIGZvciBARWxlbWVudC5pbWFnZSBlbGVtZW50XG4gICAgIG8gc3Ryb2tlIChzdHJpbmcpIHN0cm9rZSBjb2xvdXJcbiAgICAgbyBzdHJva2UtZGFzaGFycmF5IChzdHJpbmcpIFvigJzigJ0sIOKAnG5vbmXigJ0sIOKAnGAtYOKAnSwg4oCcYC5g4oCdLCDigJxgLS5g4oCdLCDigJxgLS4uYOKAnSwg4oCcYC4gYOKAnSwg4oCcYC0gYOKAnSwg4oCcYC0tYOKAnSwg4oCcYC0gLmDigJ0sIOKAnGAtLS5g4oCdLCDigJxgLS0uLmDigJ1dXG4gICAgIG8gc3Ryb2tlLWxpbmVjYXAgKHN0cmluZykgW+KAnGBidXR0YOKAnSwg4oCcYHNxdWFyZWDigJ0sIOKAnGByb3VuZGDigJ1dXG4gICAgIG8gc3Ryb2tlLWxpbmVqb2luIChzdHJpbmcpIFvigJxgYmV2ZWxg4oCdLCDigJxgcm91bmRg4oCdLCDigJxgbWl0ZXJg4oCdXVxuICAgICBvIHN0cm9rZS1taXRlcmxpbWl0IChudW1iZXIpXG4gICAgIG8gc3Ryb2tlLW9wYWNpdHkgKG51bWJlcilcbiAgICAgbyBzdHJva2Utd2lkdGggKG51bWJlcikgc3Ryb2tlIHdpZHRoIGluIHBpeGVscywgZGVmYXVsdCBpcyAnMSdcbiAgICAgbyB0YXJnZXQgKHN0cmluZykgdXNlZCB3aXRoIGhyZWZcbiAgICAgbyB0ZXh0IChzdHJpbmcpIGNvbnRlbn
57601RzIG9mIHRoZSB0ZXh0IGVsZW1lbnQuIFVzZSBgXFxuYCBmb3IgbXVsdGlsaW5lIHRleHRcbiAgICAgbyB0ZXh0LWFuY2hvciAoc3RyaW5nKSBb4oCcYHN0YXJ0YOKAnSwg4oCcYG1pZGRsZWDigJ0sIOKAnGBlbmRg4oCdXSwgZGVmYXVsdCBpcyDigJxgbWlkZGxlYOKAnVxuICAgICBvIHRpdGxlIChzdHJpbmcpIHdpbGwgY3JlYXRlIHRvb2x0aXAgd2l0aCBhIGdpdmVuIHRleHRcbiAgICAgbyB0cmFuc2Zvcm0gKHN0cmluZykgc2VlIEBFbGVtZW50LnRyYW5zZm9ybVxuICAgICBvIHdpZHRoIChudW1iZXIpXG4gICAgIG8geCAobnVtYmVyKVxuICAgICBvIHkgKG51bWJlcilcbiAgICAgPiBHcmFkaWVudHNcbiAgICAgKiBMaW5lYXIgZ3JhZGllbnQgZm9ybWF0OiDigJxg4oC5YW5nbGXigLot4oC5Y29sb3Vy4oC6Wy3igLljb2xvdXLigLpbOuKAuW9mZnNldOKAul1dKi3igLljb2xvdXLigLpg4oCdLCBleGFtcGxlOiDigJxgOTAtI2ZmZi0jMDAwYOKAnSDigJMgOTDCsFxuICAgICAqIGdyYWRpZW50IGZyb20gd2hpdGUgdG8gYmxhY2sgb3Ig4oCcYDAtI2ZmZi0jZjAwOjIwLSMwMDBg4oCdIOKAkyAwwrAgZ3JhZGllbnQgZnJvbSB3aGl0ZSB2aWEgcmVkIChhdCAyMCUpIHRvIGJsYWNrLlxuICAgICAqXG4gICAgICogcmFkaWFsIGdyYWRpZW50OiDigJxgclso4oC5ZnjigLosIOKAuWZ54oC6KV3igLljb2xvdXLigLpbLeKAuWNvbG91cuKAuls64oC5b2Zmc2V04oC6XV0qLeKAuWNvbG91cuKAumDigJ0sIGV4YW1wbGU6IOKAnGByI2ZmZi0jMDAwYOKAnSDigJNcbiAgICAgKiBncmFkaWVudCBmcm9tIHdoaXRlIHRvIGJsYWNrIG9yIOKAnGByKDAuMjUsIDAuNzUpI2ZmZi0jMDAwYOKAnSDigJMgZ3JhZGllbnQgZnJvbSB3aGl0ZSB0byBibGFjayB3aXRoIGZvY3VzIHBvaW50XG4gICAgICogYXQgMC4yNSwgMC43NS4gRm9jdXMgcG9pbnQgY29vcmRpbmF0ZXMgYXJlIGluIDAuLjEgcmFuZ2UuIFJhZGlhbCBncmFkaWVudHMgY2FuIG9ubHkgYmUgYXBwbGllZCB0byBjaXJjbGVzIGFuZCBlbGxpcHNlcy5cbiAgICAgPiBQYXRoIFN0cmluZ1xuICAgICAjIDxwPlBsZWFzZSByZWZlciB0byA8YSBocmVmPVwiaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHL3BhdGhzLmh0bWwjUGF0aERhdGFcIiB0aXRsZT1cIkRldGFpbHMgb2YgYSBwYXRo4oCZcyBkYXRhIGF0dHJpYnV0ZeKAmXMgZm9ybWF0IGFyZSBkZXNjcmliZWQgaW4gdGhlIFNWRyBzcGVjaWZpY2F0aW9uLlwiPlNWRyBkb2N1bWVudGF0aW9uIHJlZ2FyZGluZyBwYXRoIHN0cmluZzwvYT4uIFJhcGhhw6tsIGZ1bGx5IHN1cHBvcnRzIGl0LjwvcD5cbiAgICAgPiBDb2xvdXIgUGFyc2luZ1xuICAgICAjIDx1bD5cbiAgICAgIyAgICAgPGxpPkNvbG91ciBuYW1lICjigJw8Y29kZT5yZWQ8L2NvZGU+4oCdLCDigJw8Y29kZT5ncmVlbjwvY29kZT7igJ0sIOKAnDxjb2RlPmNvcm5mbG93ZXJibHVlPC9jb2RlPuKAnSwgZXRjKTwvbGk+XG4gICAgICMgICAgIDxsaT4j4oCi4oCi4oCiIOKAlCBzaG9ydGVuZWQgSFRNTCBjb2xvdXI6ICjigJw8Y29kZT4jMDAwPC9jb2RlPuKAnSwg4oCcPGNvZGU+I2ZjMDwvY29kZT7igJ0sIGV0Yyk8L2xpPlxuICAgICAjICAgICA8bGk+I+KAouKAouKAouKAouKAouKAoiDigJQgZnVsbCBsZW5ndGggSFRNTCBjb2xvdXI6ICjigJw8Y29kZT4jMDAwMDAwPC9jb2RlPuKAnSwg4oCcPGNvZGU+I2JkMjMwMDwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYijigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgcmVkLCBncmVlbiBhbmQgYmx1ZSBjaGFubmVsc+KAmSB2YWx1ZXM6ICjigJw8Y29kZT5yZ2IoMjAwLCZuYnNwOzEwMCwmbmJzcDswKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYijigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU6ICjigJw8Y29kZT5yZ2IoMTAwJSwmbmJzcDsxNzUlLCZuYnNwOzAlKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPnJnYmEo4oCi4oCi4oCiLCDigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgcmVkLCBncmVlbiBhbmQgYmx1ZSBjaGFubmVsc+KAmSB2YWx1ZXM6ICjigJw8Y29kZT5yZ2JhKDIwMCwmbmJzcDsxMDAsJm5ic3A7MCwgLjUpPC9jb2RlPuKAnSk8L2xpPlxuICAgICAjICAgICA8bGk+cmdiYSjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU6ICjigJw8Y29kZT5yZ2JhKDEwMCUsJm5ic3A7MTc1JSwmbmJzcDswJSwgNTAlKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPmhzYijigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgaHVlLCBzYXR1cmF0aW9uIGFuZCBicmlnaHRuZXNzIHZhbHVlczogKOKAnDxjb2RlPmhzYigwLjUsJm5ic3A7MC4yNSwmbmJzcDsxKTwvY29kZT7igJ0pPC9saT5cbiAgICAgIyAgICAgPGxpPmhzYijigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU8L2xpPlxuICAgICAjICAgICA8bGk+aHNiYSjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgd2l0aCBvcGFjaXR5PC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiKSDigJQgYWxtb3N0IHRoZSBzYW1lIGFzIGhzYiwgc2VlIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0hTTF9hbmRfSFNWXCIgdGl0bGU9XCJIU0wgYW5kIEhTViAtIFdpa2lwZWRpYSwgdGhlIGZyZWUgZW5jeWNsb3BlZGlhXCI+V2lraXBlZGlhIHBhZ2U8L2E+PC9saT5cbiAgICAgIyAgICAgPGxpPmhzbCjigKLigKLigKIlLCDigKLigKLigKIlLCDigKLigKLigKIlKSDigJQgc2FtZSBhcyBhYm92ZSwgYnV0IGluICU8L2xpPlxuICAgICAjICAgICA8bGk+aHNsYSjigKLigKLigKIsIOKAouKAouKAoiwg4oCi4oCi4oCiLCDigKLigKLigKIpIOKAlCBzYW1lIGFzIGFib3ZlLCBidXQgd2l0aCBvcGFjaXR5PC9saT5cbiAgICAgIyAgICAgPGxpPk9wdGlvbmFsbHkgZm9yIGhzYiBhbmQgaHNsIHlvdSBjb3VsZCBzcGVjaWZ5IGh1ZSBhcyBhIGRlZ3JlZTog4oCcPGNvZGU+aHNsKDI0MGRlZywmbmJzcDsxLCZuYnNwOy41KTwvY29kZT7igJ0gb3IsIGlmIHlvdSB3YW50IHRvIGdvIGZhbmN5LCDigJw8Y29kZT5oc2woMjQwwrAsJm5ic3A7MSwmbmJzcDsuNSk8L2NvZGU+4oCdPC9saT5cbiAgICAgIyA8L3VsPlxuICAgIFxcKi9cbiAgICBlbHByb3RvLmF0dHIgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgI
57601H1cbiAgICAgICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYSBpbiB0aGlzLmF0dHJzKSBpZiAodGhpcy5hdHRyc1toYXNdKGEpKSB7XG4gICAgICAgICAgICAgICAgcmVzW2FdID0gdGhpcy5hdHRyc1thXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy5ncmFkaWVudCAmJiByZXMuZmlsbCA9PSBcIm5vbmVcIiAmJiAocmVzLmZpbGwgPSByZXMuZ3JhZGllbnQpICYmIGRlbGV0ZSByZXMuZ3JhZGllbnQ7XG4gICAgICAgICAgICByZXMudHJhbnNmb3JtID0gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcInN0cmluZ1wiKSkge1xuICAgICAgICAgICAgaWYgKG5hbWUgPT0gXCJmaWxsXCIgJiYgdGhpcy5hdHRycy5maWxsID09IFwibm9uZVwiICYmIHRoaXMuYXR0cnMuZ3JhZGllbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hdHRycy5ncmFkaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuYW1lID09IFwidHJhbnNmb3JtXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuYW1lcyA9IG5hbWUuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICBvdXQgPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG5hbWVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBuYW1lID0gbmFtZXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKG5hbWUgaW4gdGhpcy5hdHRycykge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSB0aGlzLmF0dHJzW25hbWVdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbbmFtZV0sIFwiZnVuY3Rpb25cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0W25hbWVdID0gdGhpcy5wYXBlci
576015jdXN0b21BdHRyaWJ1dGVzW25hbWVdLmRlZjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSBSLl9hdmFpbGFibGVBdHRyc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaWkgLSAxID8gb3V0IDogb3V0W25hbWVzWzBdXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCAmJiBSLmlzKG5hbWUsIFwiYXJyYXlcIikpIHtcbiAgICAgICAgICAgIG91dCA9IHt9O1xuICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBuYW1lLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvdXRbbmFtZVtpXV0gPSB0aGlzLmF0dHIobmFtZVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0ge307XG4gICAgICAgICAgICBwYXJhbXNbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChuYW1lICE9IG51bGwgJiYgUi5pcyhuYW1lLCBcIm9iamVjdFwiKSkge1xuICAgICAgICAgICAgcGFyYW1zID0gbmFtZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmF0dHIuXCIgKyBrZXkgKyBcIi5cIiArIHRoaXMuaWQsIHRoaXMsIHBhcmFtc1trZXldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGtleSBpbiB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMpIGlmICh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShrZXkpICYmIHBhcmFtc1toYXNdKGtleSkgJiYgUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgdmFyIHBhciA9IHRoaXMucGFwZXIuY3VzdG9tQXR0cmlidXRlc1trZXldLmFwcGx5KHRoaXMsIFtdLmNvbmNhdChwYXJhbXNba2V5XSkpO1xuICAgICAgICAgICAgdGhpcy5hdHRyc1trZXldID0gcGFyYW1zW2tleV07XG4gICAgICAgICAgICBmb3IgKHZhciBzdWJrZXkgaW4gcGFyKSBpZiAocGFyW2hhc10oc3Via2V5KSkge1xuICAgICAgICAgICAgICAgIHBhcmFtc1tzdWJrZXldID0gcGFyW3N1YmtleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2V0RmlsbEFuZFN0cm9rZSh0aGlzLCBwYXJhbXMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBFbGVtZW50LnRvRnJvbnRcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE1vdmVzIHRoZSBlbGVtZW50IHNvIGl0IGlzIHRoZSBjbG9zZXN0IHRvIHRoZSB2aWV3ZXLigJlzIGV5ZXMsIG9uIHRvcCBvZiBvdGhlciBlbGVtZW50cy5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRvRnJvbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlID0gZ2V0UmVhbE5vZGUodGhpcy5ub2RlKTtcbiAgICAgICAgbm9kZS5wYXJlbnROb2RlLmFwcGVuZENoaWxkKG5vZGUpO1xuICAgICAgICB2Y
57601XIgc3ZnID0gdGhpcy5wYXBlcjtcbiAgICAgICAgc3ZnLnRvcCAhPSB0aGlzICYmIFIuX3RvZnJvbnQodGhpcywgc3ZnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC50b0JhY2tcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIE1vdmVzIHRoZSBlbGVtZW50IHNvIGl0IGlzIHRoZSBmdXJ0aGVzdCBmcm9tIHRoZSB2aWV3ZXLigJlzIGV5ZXMsIGJlaGluZCBvdGhlciBlbGVtZW50cy5cbiAgICAgPSAob2JqZWN0KSBARWxlbWVudFxuICAgIFxcKi9cbiAgICBlbHByb3RvLnRvQmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vZGUgPSBnZXRSZWFsTm9kZSh0aGlzLm5vZGUpO1xuICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgcGFyZW50Tm9kZS5maXJzdENoaWxkKTtcbiAgICAgICAgUi5fdG9iYWNrKHRoaXMsIHRoaXMucGFwZXIpO1xuICAgICAgICB2YXIgc3ZnID0gdGhpcy5wYXBlcjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogRWxlbWVudC5pbnNlcnRBZnRlclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogSW5zZXJ0cyBjdXJyZW50IG9iamVjdCBhZnRlciB0aGUgZ2l2ZW4gb25lLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaW5zZXJ0QWZ0ZXIgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVkIHx8ICFlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBub2RlID0gZ2V0UmVhbE5vZGUodGhpcy5ub2RlKTtcbiAgICAgICAgdmFyIGFmdGVyTm9kZSA9IGdldFJlYWxOb2RlKGVsZW1lbnQubm9kZSB8fCBlbGVtZW50W2VsZW1lbnQubGVuZ3RoIC0gMV0ubm9kZSk7XG4gICAgICAgIGlmIChhZnRlck5vZGUubmV4dFNpYmxpbmcpIHtcbiAgICAgICAgICAgIGFmdGVyTm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShub2RlLCBhZnRlck5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWZ0ZXJOb2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgUi5faW5zZXJ0YWZ0ZXIodGhpcywgZWxlbWVudCwgdGhpcy5wYXBlcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIEVsZW1lbnQuaW5zZXJ0QmVmb3JlXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJbnNlcnRzIGN1cnJlbnQgb2JqZWN0IGJlZm9yZSB0aGUgZ2l2ZW4gb25lLlxuICAgICA9IChvYmplY3QpIEBFbGVtZW50XG4gICAgXFwqL1xuICAgIGVscHJvdG8uaW5zZXJ0QmVmb3JlID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCB8fCAhZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICB2Y
57601XIgbm9kZSA9IGdldFJlYWxOb2RlKHRoaXMubm9kZSk7XG4gICAgICAgIHZhciBiZWZvcmVOb2RlID0gZ2V0UmVhbE5vZGUoZWxlbWVudC5ub2RlIHx8IGVsZW1lbnRbMF0ubm9kZSk7XG4gICAgICAgIGJlZm9yZU5vZGUucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgYmVmb3JlTm9kZSk7XG4gICAgICAgIFIuX2luc2VydGJlZm9yZSh0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmJsdXIgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICAvLyBFeHBlcmltZW50YWwuIE5vIFNhZmFyaSBzdXBwb3J0LiBVc2UgaXQgb24geW91ciBvd24gcmlzay5cbiAgICAgICAgdmFyIHQgPSB0aGlzO1xuICAgICAgICBpZiAoK3NpemUgIT09IDApIHtcbiAgICAgICAgICAgIHZhciBmbHRyID0gJChcImZpbHRlclwiKSxcbiAgICAgICAgICAgICAgICBibHVyID0gJChcImZlR2F1c3NpYW5CbHVyXCIpO1xuICAgICAgICAgICAgdC5hdHRycy5ibHVyID0gc2l6ZTtcbiAgICAgICAgICAgIGZsdHIuaWQgPSBSLmNyZWF0ZVVVSUQoKTtcbiAgICAgICAgICAgICQoYmx1ciwge3N0ZERldmlhdGlvbjogK3NpemUgfHwgMS41fSk7XG4gICAgICAgICAgICBmbHRyLmFwcGVuZENoaWxkKGJsdXIpO1xuICAgICAgICAgICAgdC5wYXBlci5kZWZzLmFwcGVuZENoaWxkKGZsdHIpO1xuICAgICAgICAgICAgdC5fYmx1ciA9IGZsdHI7XG4gICAgICAgICAgICAkKHQubm9kZSwge2ZpbHRlcjogXCJ1cmwoI1wiICsgZmx0ci5pZCArIFwiKVwifSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodC5fYmx1cikge1xuICAgICAgICAgICAgICAgIHQuX2JsdXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0Ll9ibHVyKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdC5fYmx1cjtcbiAgICAgICAgICAgICAgICBkZWxldGUgdC5hdHRycy5ibHVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdC5ub2RlLnJlbW92ZUF0dHJpYnV0ZShcImZpbHRlclwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5jaXJjbGUgPSBmdW5jdGlvbiAoc3ZnLCB4LCB5LCByKSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJjaXJjbGVcIik7XG4gICAgICAgIHN2Zy5jYW52YXMgJiYgc3ZnLmNhbnZhcy5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIHZhciByZXMgPSBuZXcgRWxlbWVudChlbCwgc3ZnKTtcbiAgICAgICAgcmVzLmF0dHJzID0ge2N4OiB4LCBjeTogeSwgcjogciwgZmlsbDogXCJub25lXCIsIHN0cm9rZTogXCIjMDAwXCJ9O1xuICAgICAgICByZXMudHlwZSA9IFwiY2lyY2xlXCI7XG4gICAgICAgICQoZWwsIHJlcy5hdHRycyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUucmVjdCA9IGZ1bmN0aW9uIChzdmcsIHgsIHksIHcsIGgsIHIpIHtcbiAgICAgICAgdmFyIGVsID0gJChcInJlY3RcIik7XG4gICAgICAgIHN2Zy5jYW52YXMgJiYgc3ZnLmNhbnZhcy5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIHZhciByZXMgPSBuZXcgRWxlbWVudChlbCwgc3ZnKTtcbiAgICAgICAgcmVzLmF0dHJzID0ge3g6IHgsIHk6IHksIHdpZHRoOiB3LCBoZWlnaHQ6IGgsIHJ4OiByIHx8IDAsIHJ5OiByIHx8IDAsIGZpbGw6IFwibm9uZVwiLCBzdHJva2U6IFwiIzAwMFwifTtcbiAgICAgICAgcmVzLnR5cGUgPSBcInJlY3RcIjtcbiAgICAgICAgJChlbCwgcmVzLmF0dHJzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5lbGxpcHNlID0gZnVuY3Rpb24gKHN2ZywgeCwgeSwgcngsIHJ5KSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJlbGxpcHNlXCIpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57601XIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHtjeDogeCwgY3k6IHksIHJ4OiByeCwgcnk6IHJ5LCBmaWxsOiBcIm5vbmVcIiwgc3Ryb2tlOiBcIiMwMDBcIn07XG4gICAgICAgIHJlcy50eXBlID0gXCJlbGxpcHNlXCI7XG4gICAgICAgICQoZWwsIHJlcy5hdHRycyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuaW1hZ2UgPSBmdW5jdGlvbiAoc3ZnLCBzcmMsIHgsIHksIHcsIGgpIHtcbiAgICAgICAgdmFyIGVsID0gJChcImltYWdlXCIpO1xuICAgICAgICAkKGVsLCB7eDogeCwgeTogeSwgd2lkdGg6IHcsIGhlaWdodDogaCwgcHJlc2VydmVBc3BlY3RSYXRpbzogXCJub25lXCJ9KTtcbiAgICAgICAgZWwuc2V0QXR0cmlidXRlTlMoeGxpbmssIFwiaHJlZlwiLCBzcmMpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2YXIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHt4OiB4LCB5OiB5LCB3aWR0aDogdywgaGVpZ2h0OiBoLCBzcmM6IHNyY307XG4gICAgICAgIHJlcy50eXBlID0gXCJpbWFnZVwiO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnRleHQgPSBmdW5jdGlvbiAoc3ZnLCB4LCB5LCB0ZXh0KSB7XG4gICAgICAgIHZhciBlbCA9ICQoXCJ0ZXh0XCIpO1xuICAgICAgICBzdmcuY2FudmFzICYmIHN2Zy5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57601XIgcmVzID0gbmV3IEVsZW1lbnQoZWwsIHN2Zyk7XG4gICAgICAgIHJlcy5hdHRycyA9IHtcbiAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICB5OiB5LFxuICAgICAgICAgICAgXCJ0ZXh0LWFuY2hvclwiOiBcIm1pZGRsZVwiLFxuICAgICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgICAgIFwiZm9udC1mYW1pbHlcIjogUi5fYXZhaWxhYmxlQXR0cnNbXCJmb250LWZhbWlseVwiXSxcbiAgICAgICAgICAgIFwiZm9udC1zaXplXCI6IFIuX2F2YWlsYWJsZUF0dHJzW1wiZm9udC1zaXplXCJdLFxuICAgICAgICAgICAgc3Ryb2tlOiBcIm5vbmVcIixcbiAgICAgICAgICAgIGZpbGw6IFwiIzAwMFwiXG4gICAgICAgIH07XG4gICAgICAgIHJlcy50eXBlID0gXCJ0ZXh0XCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocmVzLCByZXMuYXR0cnMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnNldFNpemUgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGggfHwgdGhpcy53aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQgfHwgdGhpcy5oZWlnaHQ7XG4gICAgICAgIHRoaXMuY2FudmFzLnNldEF0dHJpYnV0ZShcIndpZHRoXCIsIHRoaXMud2lkdGgpO1xuICAgICAgICB0aGlzLmNhbnZhcy5zZXRBdHRyaWJ1dGUoXCJoZWlnaHRcIiwgdGhpcy5oZWlnaHQpO1xuICAgICAgICBpZiAodGhpcy5fdmlld0JveCkge1xuICAgICAgICAgICAgdGhpcy5zZXRWaWV3Qm94LmFwcGx5KHRoaXMsIHRoaXMuX3ZpZXdCb3gpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLmNyZWF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbiA9IFIuX2dldENvbnRhaW5lci5hcHBseSgwLCBhcmd1bWVudHMpLFxuICAgICAgICAgICAgY29udGFpbmVyID0gY29uICYmIGNvbi5jb250YWluZXI7XG4gICAgICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTVkcgY29udGFpbmVyIG5vdCBmb3VuZC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHggPSBjb24ueCxcbiAgICAgICAgICAgIHkgPSBjb24ueSxcbiAgICAgICAgICAgIHdpZHRoID0gY29uLndpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0ID0gY29uLmhlaWdodCxcbiAgICAgICAgICAgIGNudnMgPSAkKFwic3ZnXCIpLFxuICAgICAgICAgICAgY3NzID0gXCJvdmVyZmxvdzpoaWRkZW47XCIsXG4gICAgICAgICAgICBpc0Zsb2F0aW5nO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB3aWR0aCA9IHdpZHRoIHx8IDUxMjtcbiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0IHx8IDM0MjtcbiAgICAgICAgJChjbnZzLCB7XG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgICAgIHZlcnNpb246IDEuMSxcbiAgICAgICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgIHhtbG5zOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXG4gICAgICAgICAgICBcInhtbG5zOnhsaW5rXCI6IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY29udGFpbmVyID09IDEpIHtcbiAgICAgICAgICAgIGNudnMuc3R5bGUuY3NzVGV4dCA9IGNzcyArIFwicG9zaXRpb246YWJzb2x1dGU7bGVmdDpcIiArIHggKyBcInB4O3RvcDpcIiArIHkgKyBcInB4XCI7XG4gICAgICAgICAgICBSLl9nLmRvYy5ib2R5LmFwcGVuZENoaWxkKGNudnMpO1xuICAgICAgICAgICAgaXNGbG9hdGluZyA9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjbnZzLnN0eWxlLmNzc1RleHQgPSBjc3MgKyBcInBvc2l0aW9uOnJlbGF0aXZlXCI7XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0QmVmb3JlKGNudnMsIGNvbnRhaW5lci5maXJzdENoaWxkKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGNudnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnRhaW5lciA9IG5ldyBSLl9QYXBlcjtcbiAgICAgICAgY29udGFpbmVyLndpZHR
57601oID0gd2lkdGg7XG4gICAgICAgIGNvbnRhaW5lci5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGNvbnRhaW5lci5jYW52YXMgPSBjbnZzO1xuICAgICAgICBjb250YWluZXIuY2xlYXIoKTtcbiAgICAgICAgY29udGFpbmVyLl9sZWZ0ID0gY29udGFpbmVyLl90b3AgPSAwO1xuICAgICAgICBpc0Zsb2F0aW5nICYmIChjb250YWluZXIucmVuZGVyZml4ID0gZnVuY3Rpb24gKCkge30pO1xuICAgICAgICBjb250YWluZXIucmVuZGVyZml4KCk7XG4gICAgICAgIHJldHVybiBjb250YWluZXI7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuc2V0Vmlld0JveCA9IGZ1bmN0aW9uICh4LCB5LCB3LCBoLCBmaXQpIHtcbiAgICAgICAgZXZlKFwicmFwaGFlbC5zZXRWaWV3Qm94XCIsIHRoaXMsIHRoaXMuX3ZpZXdCb3gsIFt4LCB5LCB3LCBoLCBmaXRdKTtcbiAgICAgICAgdmFyIHBhcGVyU2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxuICAgICAgICAgICAgc2l6ZSA9IG1tYXgodyAvIHBhcGVyU2l6ZS53aWR0aCwgaCAvIHBhcGVyU2l6ZS5oZWlnaHQpLFxuICAgICAgICAgICAgdG9wID0gdGhpcy50b3AsXG4gICAgICAgICAgICBhc3BlY3RSYXRpbyA9IGZpdCA/IFwieE1pZFlNaWQgbWVldFwiIDogXCJ4TWluWU1pblwiLFxuICAgICAgICAgICAgdmIsXG4gICAgICAgICAgICBzdztcbiAgICAgICAgaWYgKHggPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3ZiU2l6ZSkge1xuICAgICAgICAgICAgICAgIHNpemUgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHRoaXMuX3ZiU2l6ZTtcbiAgICAgICAgICAgIHZiID0gXCIwIDAgXCIgKyB0aGlzLndpZHRoICsgUyArIHRoaXMuaGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fdmJTaXplID0gc2l6ZTtcbiAgICAgICAgICAgIHZiID0geCArIFMgKyB5ICsgUyArIHcgKyBTICsgaDtcbiAgICAgICAgfVxuICAgICAgICAkKHRoaXMuY2FudmFzLCB7XG4gICAgICAgICAgICB2aWV3Qm94OiB2YixcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86IGFzcGVjdFJhdGlvXG4gICAgICAgIH0pO1xuICAgICAgICB3aGlsZSAoc2l6ZSAmJiB0b3ApIHtcbiAgICAgICAgICAgIHN3ID0gXCJzdHJva2Utd2lkdGhcIiBpbiB0b3AuYX
57601R0cnMgPyB0b3AuYXR0cnNbXCJzdHJva2Utd2lkdGhcIl0gOiAxO1xuICAgICAgICAgICAgdG9wLmF0dHIoe1wic3Ryb2tlLXdpZHRoXCI6IHN3fSk7XG4gICAgICAgICAgICB0b3AuXy5kaXJ0eSA9IDE7XG4gICAgICAgICAgICB0b3AuXy5kaXJ0eVQgPSAxO1xuICAgICAgICAgICAgdG9wID0gdG9wLnByZXY7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmlld0JveCA9IFt4LCB5LCB3LCBoLCAhIWZpdF07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlbmRlcmZpeFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogRml4ZXMgdGhlIGlzc3VlIG9mIEZpcmVmb3ggYW5kIElFOSByZWdhcmRpbmcgc3VicGl4ZWwgcmVuZGVyaW5nLiBJZiBwYXBlciBpcyBkZXBlbmRlbnRcbiAgICAgKiBvbiBvdGhlciBlbGVtZW50cyBhZnRlciByZWZsb3cgaXQgY291bGQgc2hpZnQgaGFsZiBwaXhlbCB3aGljaCBjYXVzZSBmb3IgbGluZXMgdG8gbG9zdCB0aGVpciBjcmlzcG5lc3MuXG4gICAgICogVGhpcyBtZXRob2QgZml4ZXMgdGhlIGlzc3VlLlxuICAgICAqKlxuICAgICAgIFNwZWNpYWwgdGhhbmtzIHRvIE1hcml1c3ogTm93YWsgKGh0dHA6Ly93d3cubWVkaWtvby5jb20vKSBmb3IgdGhpcyBtZXRob2QuXG4gICAgXFwqL1xuICAgIFIucHJvdG90eXBlLnJlbmRlcmZpeCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNudnMgPSB0aGlzLmNhbnZhcyxcbiAgICAgICAgICAgIHMgPSBjbnZzLnN0eWxlLFxuICAgICAgICAgICAgcG9zO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcG9zID0gY252cy5nZXRTY3JlZW5DVE0oKSB8fCBjbnZzLmNyZWF0ZVNWR01hdHJpeCgpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBwb3MgPSBjbnZzLmNyZWF0ZVNWR01hdHJpeCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWZ0ID0gLXBvcy5lICUgMSxcbiAgICAgICAgICAgIHRvcCA9IC1wb3MuZiAlIDE7XG4gICAgICAgIGlmIChsZWZ0IHx8IHRvcCkge1xuICAgICAgICAgICAgaWYgKGxlZnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sZWZ0ID0gKHRoaXMuX2xlZnQgKyBsZWZ0KSAlIDE7XG4gICAgICAgICAgICAgICAgcy5sZWZ0ID0gdGhpcy5fbGVmdCArIFwicHhcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0b3ApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl90b3AgPSAodGhpcy5fdG9wICsgdG9wKSAlIDE7XG4gICAgICAgICAgICAgICAgcy50b3AgPSB0aGlzLl90b3AgKyBcInB4XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBQYXBlci5jbGVhclxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ2xlYXJzIHRoZSBwYXBlciwgaS5lLiByZW1vdmVzIGFsbCB0aGUgZWxlbWVudHMuXG4gICAgXFwqL1xuICAgIFIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBSLmV2ZShcInJhcGhhZWwuY2xlYXJcIiwgdGhpcyk7XG4gICAgICAgIHZhciBjID0gdGhpcy5jYW52YXM7XG4gICAgICAgIHdoaWxlIChjLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgIGMucmVtb3ZlQ2hpbGQoYy5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJvdHRvbSA9IHRoaXMudG9wID0gbnVsbDtcbiAgICAgICAgKHRoaXMuZGVzYyA9ICQoXCJkZXNjXCIpKS5hcHBlbmRDaGlsZChSLl9nLmRvYy5jcmVhdGVUZXh0Tm9kZShcIkNyZWF0ZWQgd2l0aCBSYXBoYVxceGVibCBcIiArIFIudmVyc2lvbikpO1xuICAgICAgICBjLmFwcGVuZENoaWxkKHRoaXMuZGVzYyk7XG4gICAgICAgIGMuYXBwZW5kQ2hpbGQodGhpcy5kZWZzID0gJChcImRlZnNcIikpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIFBhcGVyLnJlbW92ZVxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogUmVtb3ZlcyB0aGUgcGFwZXIgZnJvbSB0aGUgRE9NLlxuICAgIFxcKi9cbiAgICBSLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGV2ZShcInJhcGhhZWwucmVtb3ZlXCIsIHRoaXMpO1xuICAgICAgICB0aGlzLmNhbnZhcy5wYXJlbnROb2RlICYmIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSB0eXBlb2YgdGhpc1tpXSA9PSBcImZ1bmN0aW9uXCIgPyBSLl9yZW1vdmVkRmFjdG9yeShpKSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHZhciBzZXRwcm90byA9IFIuc3Q7XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSAmJiAhc2V0cHJvdG9baGFzXShtZXRob2QpKSB7XG4gICAgICAgIHNldHByb3RvW21ldGhvZF0gPSAoZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBlbFttZXRob2RuYW1lXS5hcHBseShlbCwgYXJnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pKG1ldGhvZCk7XG4gICAgfVxufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./dev/raphael.svg.js\n"); 57602 57603/***/ }), 57604
57605/***/ "./dev/raphael.vml.js": 57606/*!****************************!*\ 57607 !*** ./dev/raphael.vml.js ***! 57608 \****************************/ 57609/*! no static exports found */ 57610/***/ (function(module, exports, __webpack_require__) { 57611 57612eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! ./raphael.core */ \"./dev/raphael.core.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(R) {\n if (R && !R.vml) {\n return;\n }\n\n var has = \"hasOwnProperty\",\n Str = String,\n toFloat = parseFloat,\n math = Math,\n round = math.round,\n mmax = math.max,\n mmin = math.min,\n abs = math.abs,\n fillString = \"fill\",\n separator = /[, ]+/,\n eve = R.eve,\n ms = \" progid:DXImageTransform.Microsoft\",\n S = \" \",\n E = \"\",\n map = {M: \"m\", L: \"l\", C: \"c\", Z: \"x\", m: \"t\", l: \"r\", c: \"v\", z: \"x\"},\n bites = /([clmz]),?([^clmz]*)/gi,\n blurregexp = / progid:\\S+Blur\\([^\\)]+\\)/g,\n val = /-?[^,\\s-]+/g,\n cssDot = \"position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)\",\n zoom = 21600,\n pathTypes = {path: 1, rect: 1, image: 1},\n ovalTypes = {circle: 1, ellipse: 1},\n path2vml = function (path) {\n var total = /[ahqstv]/ig,\n command = R._pathToAbsolute;\n Str(path).match(total) && (command = R._path2curve);\n total = /[clmz]/g;\n if (command == R._pathToAbsolute && !Str(path).match(total)) {\n var res = Str(path).replace(bites, function (all, command, args) {\n var vals = [],\n isMove = command.toLowerCase() == \"m\",\n res = map[command];\n args.replace(val, function (value) {\n if (isMove && vals.length == 2) {\n res += vals + map[command == \"m\" ? \"l\" : \"L\"];\n vals = [];\n }\n vals.push(round(value * zoom));\n });\n return res + vals;\n });\n return res;\n }\n var pa = command(path), p, r;\n res = [];\n for (var i = 0, ii = pa.length; i < ii; i++) {\n p = pa[i];\n r = pa[i][0].toLowerCase();\n r == \"z\" && (r = \"x\");\n for (var j = 1, jj = p.length; j < jj; j++) {\n r += round(p[j] * zoom) + (j != jj - 1 ? \",\" : E);\n }\n res.push(r);\n }\n return res.join(S);\n },\n compensation = function (deg, dx, dy) {\n var m = R.matrix();\n m.rotate(-deg, .5, .5);\n return {\n dx: m.x(dx, dy),\n dy: m.y(dx, dy)\n };\n },\n setCoords = function (p, sx, sy, dx, dy, deg) {\n var _ = p._,\n m = p.matrix,\n fillpos = _.fillpos,\n o = p.node,\n s = o.style,\n y = 1,\n flip = \"\",\n dxdy,\n kx = zoom / sx,\n ky = zoom / sy;\n s.visibility = \"hidden\";\n if (!sx || !sy) {\n return;\n }\n o.coordsize = abs(kx) + S + abs(ky);\n s.rotation = deg * (sx * sy < 0 ? -1 : 1);\n if (deg) {\n var c = compensation(deg, dx, dy);\n dx = c.dx;\n dy = c.dy;\n }\n sx < 0 && (flip += \"x\");\n sy < 0 && (flip += \" y\") && (y = -1);\n s.flip = flip;\n o.coordorigin = (dx * -kx) + S + (dy * -ky);\n if (fillpos || _.fillsize) {\n var fill = o.getElementsByTagName(fillString);\n fill = fill && fill[0];\n o.removeChild(fill);\n if (fillpos) {\n c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));\n fill.position = c.dx * y + S + c.dy * y;\n }\n if (_.fillsize) {\n fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);\n }\n o.appendChild(fill);\n }\n s.visibility = \"visible\";\n };\n R.toString = function () {\n return \"Your browser doesn\\u2019t support SVG. Falling down to VML.\\nYou are running Rapha\\xebl \" + this.version;\n };\n var addArrow = function (o, value, isEnd) {\n var values = Str(value).toLowerCase().split(\"-\"),\n se = isEnd ? \"end\" : \"start\",\n i = values.length,\n type = \"classic\",\n w = \"medium\",\n h = \"medium\";\n while (i--) {\n switch (values[i]) {\n case \"block\":\n case \"classic\":\n case \"oval\":\n case \"diamond\":\n case \"open\":\n case \"none\":\n type = values[i];\n break;\n case \"wide\":\n case \"narrow\": h = values[i]; break;\n case \"long\":\n case \"short\": w = values[i]; break;\n }\n }\n var stroke = o.node.getElementsByTagName(\"stroke\")[0];\n stroke[se + \"arrow\"] = type;\n stroke[se + \"arrowlength\"] = w;\n stroke[se + \"arrowwidth\"] = h;\n },\n setFillAndStroke = function (o, params) {\n // o.paper.canvas.style.display = \"none\";\n o.attrs = o.attrs || {};\n var node = o.node,\n a = o.attrs,\n s = node.style,\n xy,\n newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),\n isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),\
57612n res = o;\n\n\n for (var par in params) if (params[has](par)) {\n a[par] = params[par];\n }\n if (newpath) {\n a.path = R._getPath[o.type](o);\n o._.dirty = 1;\n }\n params.href && (node.href = params.href);\n params.title && (node.title = params.title);\n params.target && (node.target = params.target);\n params.cursor && (s.cursor = params.cursor);\n \"blur\" in params && o.blur(params.blur);\n if (params.path && o.type == \"path\" || newpath) {\n node.path = path2vml(~Str(a.path).toLowerCase().indexOf(\"r\") ? R._pathToAbsolute(a.path) : a.path);\n o._.dirty = 1;\n if (o.type == \"image\") {\n o._.fillpos = [a.x, a.y];\n o._.fillsize = [a.width, a.height];\n setCoords(o, 1, 1, 0, 0, 0);\n }\n }\n \"transform\" in params && o.transform(params.transform);\n if (isOval) {\n var cx = +a.cx,\n cy = +a.cy,\n rx = +a.rx ||
57612+a.r || 0,\n ry = +a.ry || +a.r || 0;\n node.path = R.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));\n o._.dirty = 1;\n }\n if (\"clip-rect\" in params) {\n var rect = Str(params[\"clip-rect\"]).split(separator);\n if (rect.length == 4) {\n rect[2] = +rect[2] + (+rect[0]);\n rect[3] = +rect[3] + (+rect[1]);\n var div = node.clipRect || R._g.doc.createElement(\"div\"),\n dstyle = div.style;\n dstyle.clip = R.format(\"rect({1}px {2}px {3}px {0}px)\", rect);\n if (!node.clipRect) {\n dstyle.position = \"absolute\";\n dstyle.top = 0;\n dstyle.left = 0;\n dstyle.width = o.paper.width + \"px\";\n dstyle.height = o.paper.height + \"px\";\n node.parentNode.insertBefore(div, node);\n div.appendChild(node);\n node.clipRect = div;\n }\n }\n if (!params[\"clip-rect\"]) {\n node.clipRect && (node.clipRect.style.clip = \"auto\");\n }\n }\n if (o.textpath) {\n var textpathStyle = o.textpath.style;\n params.font && (textpathStyle.font = params.font);\n params[\"font-family\"] && (textpathStyle.fontFamily = '\"' + params[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g, E) + '\"');\n params[\"font-size\"] && (textpathStyle.fontSize = params[\"font-size\"]);\n params[\"font-weight\"] && (textpathStyle.fontWeight = params[\"font-weight\"]);\n params[\"font-style\"] && (textpathStyle.fontStyle = params[\"font-style\"]);\n }\n if (\"arrow-start\" in params) {\n addArrow(res, params[\"arrow-start\"]);\n }\n if (\"arrow-end\" in params) {\n addArrow(res, params[\"arrow-end\"], 1);\n }\n if (params.opacity != null ||\n params.fill != null ||\n params.src != null ||\n params.stroke != null ||\n params[\"stroke-width\"] != null ||\n params[\"stroke-opacity\"] != null ||\n params[\"fill-opacity\"] != null ||\n params[\"stroke-dasharray\"] != null ||\n params[\"stroke-miterlimit\"] != null ||\n params[\"stroke-linejoin\"] != null ||\n params[\"stroke-linecap\"] != null) {\n var fill = node.getElementsByTagName(fillString),\n newfill = false;\n fill = fill && fill[0];\n !fill && (newfill = fill = createNode(fillString));\n if (o.type == \"image\" && params.src) {\n fill.src = params.src;\n }\n params.fill && (fill.on = true);\n if (fill.on == null || params.fill == \"none\" || params.fill === null) {\n fill.on = false;\n }\n if (fill.on && params.fill) {\n var isURL = Str(params.fill).match(R._ISURL);\n if (isURL) {\n fill.parentNode == node && node.removeChild(fill);\n fill.rotate = true;\n fill.src = isURL[1];\n fill.type = \"tile\";\n var bbox = o.getBBox(1);\n fill.position = bbox.x + S + bbox.y;\n o._.fillpos = [bbox.x, bbox.y];\n\n R._preload(isURL[1], function () {\n o._.fillsize = [this.offsetWidth, this.offsetHeight];\n });\n } else {\n fill.color = R.getRGB(params.fill).hex;\n fill.src = E;\n fill.type = \"solid\";\n if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != \"r\") && addGradientFill(res, params.fill, fill)) {\
57612n a.fill = \"none\";\n a.gradient = params.fill;\n fill.rotate = false;\n }\n }\n }\n if (\"fill-opacity\" in params || \"opacity\" in params) {\n var opacity = ((+a[\"fill-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);\n opacity = mmin(mmax(opacity, 0), 1);\n fill.opacity = opacity;\n if (fill.src) {\n fill.color = \"none\";\n }\n }\n node.appendChild(fill);\n var stroke = (node.getElementsByTagName(\"stroke\") && node.getElementsByTagName(\"stroke\")[0]),\n newstroke = false;\n !stroke && (newstroke = stroke = createNode(\"stroke\"));\n if ((params.stroke && params.stroke != \"none\") ||\n params[\"stroke-width\"] ||\n params[\"stroke-opacity\"] != null ||\n params[\"stroke-dasharray\"] ||\n params[\"stroke-miterlimit\"] ||\n params[\"stroke-linejoin\"] ||\n params[\"stroke-linecap\"]) {\n stroke.on = true;\n }\n (params.stroke == \"none\" || params.stroke === null || stroke.on == null || params.stroke == 0 || params[\"stroke-width\"] == 0) && (stroke.on = false);\n var strokeColor = R.getRGB(params.stroke);\n stroke.on && params.stroke && (stroke.color = strokeColor.hex);\n opacity = ((+a[\"stroke-opacity\"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);\n var width = (toFloat(params[\"stroke-width\"]) || 1) * .75;\n opacity = mmin(mmax(opacity, 0), 1);\n params[\"stroke-width\"] == null && (width = a[\"stroke-width\"]);\n params[\"stroke-width\"] && (stroke.weight = width);\n width && width < 1 && (opacity *= width) && (stroke.weight = 1);\n stroke.opacity = opacity;\n\n params[\"stroke-linejoin\"] && (stroke.joinstyle = params[\"stroke-linejoin\"] || \"miter\");\n stroke.miterlimit = params[\"stroke-miterlimit\"] || 8;\n params[\"stroke-linecap\"] && (stroke.endcap = params[\"stroke-linecap\"] == \"butt\" ? \"flat\" : params[\"stroke-linecap\"] == \"square\" ? \"square\" : \"round\");\n if (\"stroke-dasharray\" in params) {\n var dasharray = {\n \"-\": \"shortdash\",\n \".\": \"shortdot\",\n \"-.\": \"shortdashdot\",\n \"-..\": \"shortdashdotdot\",\n \". \": \"dot\",\n \"- \": \"dash\",\n \"--\": \"longdash\",\n \"- .\": \"dashdot\",\n \"--.\": \"longdashdot\",\n \"--..\": \"longdashdotdot\"\n };\n stroke.dashstyle = dasharray[has](params[\"stroke-dasharray\"]) ? dasharray[params[\"stroke-dasharray\"]] : E;\n }\n newstroke && node.appendChild(stroke);\n }\n if (res.type == \"text\") {\n res.paper.canvas.style.display = E;\n var span = res.paper.span,\n m = 100,\n fontSize = a.font && a.font.match(/\\d+(?:\\.\\d*)?(?=px)/);\n s = span.style;\n a.font && (s.font = a.font);\n a[\"font-family\"] && (s.fontFamily = a[\"font-family\"]);\n a[\"font-weight\"] && (s.fontWeight = a[\"font-weight\"]);\n a[\"font-style\"] && (s.fontStyle = a[\"font-style\"]);\n fontSize = toFloat(a[\"font-size\"] || fontSize && fontSize[0]) || 10;\n s.fontSize = fontSize * m + \"px\";\n res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, \"<\").replace(/&/g, \"&
57612\").replace(/\\n/g, \"<br>\"));\n var brect = span.getBoundingClientRect();\n res.W = a.w = (brect.right - brect.left) / m;\n res.H = a.h = (brect.bottom - brect.top) / m;\n // res.paper.canvas.style.display = \"none\";\n res.X = a.x;\n res.Y = a.y + res.H / 2;\n\n (\"x\" in params || \"y\" in params) && (res.path.v = R.format(\"m{0},{1}l{2},{1}\", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));\n var dirtyattrs = [\"x\", \"y\", \"text\", \"font\", \"font-family\", \"font-weight\", \"font-style\", \"font-size\"];\n for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {\n res._.dirty = 1;\n break;\n }\n\n // text-anchor emulation\n switch (a[\"text-anchor\"]) {\n case \"start\":\n res.textpath.style[\"v-text-align\"] = \"left\";\n res.bbx = res.W / 2;\n break;\n case \"end\":\n res.textpath.style[\"v-text-align\"] = \"right\";\n res.bbx = -res.W / 2;\n break;\n default:\n res.textpath.style[\"v-text-align\"] = \"center\";\n res.bbx = 0;\n break;\n }\n res.textpath.style[\"v-text-kern\"] = true;\n }\n // res.paper.canvas.style.display = E;\n },\n addGradientFill = function (o, gradient, fill) {\n o.attrs = o.attrs || {};\n var attrs = o.attrs,\n pow = Math.pow,\n opacity,\n oindex,\n type = \"linear\",\n fxfy = \".5 .5\";\n o.attrs.gradient = gradient;\n gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {\n type = \"radial\";\n if (fx && fy) {\n fx = toFloat(fx);\n fy = toFloat(fy);\n pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);\n fxfy = fx + S + fy;\n }\n return E;\n });\n gradient = gradient.split(/\\s*\\-\\s*/);\n if (type == \"linear\") {\n var angle = gradient.shift();\n angle = -toFloat(angle);\n if (isNaN(angle)) {\n return null;\n }\n }\n var dots = R._parseDots(gradient);\n if (!dots) {\n return null;\n }\n o = o.shape || o.node;\n if (dots.length) {\n o.removeChild(fill);\n fill.on = true;\n fill.method = \"none\";\n fill.color = dots[0].color;\n fill.color2 = dots[dots.length - 1].color;\n var clrs = [];\n for (var i = 0, ii = dots.length; i < ii; i++) {\n dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);\n }\n fill.colors = clrs.length ? clrs.join() : \"0% \" + fill.color;\n if (type == \"radial\") {\n fill.type = \"gradientTitle\";\n fill.focus = \"100%\";\n fill.focussize = \"0 0\";\n fill.focusposition = fxfy;\n fill.angle = 0;\n } else {\n // fill.rotate= true;\n fill.type = \"gradient\";\n fill.angle = (270 - angle) % 360;\n }\n o.appendChild(fill);\n }\n return 1;\n },\n Element = function (node, vml) {\n this[0] = this.node = node;\n node.raphael = true;\n this.id = R._oid++;\n node.raphaelid = this.id;\n this.X = 0;\n this.Y = 0;\n this.attrs = {};\n this.paper = vml;\n this.matrix = R.matrix();\n this._ = {\n transform: [],\n sx: 1,\n sy: 1,\n dx: 0,\n dy: 0,\n deg: 0,\n dirty: 1,\n dirtyT: 1\n };\n !vml.bottom && (vml.bottom = this);\n this.prev = vml.top;\n vml.top && (vml.top.next = this);\n vml.top = this;\n this.next = null;\n };\n var elproto = R.el;\n\n Element.prototype = elproto;\n elproto.constructor = Element;\n elproto.transform = function (tstr) {\n if (tstr == null) {\n return this._.transform;\n }\n var vbs = this.paper._viewBoxShift,\n vbt = vbs ? \"s\" + [vbs.scale, vbs.scale] + \"-1-1t\" + [vbs.dx, vbs.dy] : E,\n oldt;\n if (vbs) {\n oldt = tstr = Str(tstr).replace(/\\.{3}|\\u2026/g, this._.transform || E);\n }\n R._extractTransform(this, vbt + tstr);\n var matrix = this.matrix.clone(),\n skew = this.skew,\n o = this.node,\n split,\n isGrad = ~Str(this.attrs.fill).indexOf(\"-\"),\n isPatt = !Str(this.attrs.fill).indexOf(\"url(\");\n matrix.translate(1, 1);\n if (isPatt || isGrad || this.type == \"image\") {\n skew.matrix = \"1 0 0 1\";\n skew.offset = \"0 0\";\n split = matrix.split();\n if ((isGrad && split.noRotation) || !split.isSimple) {\n o.style.filter = matrix.toFilter();\n var bb = this.getBBox(),\n bbt = this.getBBox(1),\n dx = bb.x - bbt.x,\n dy = bb.y - bbt.y;\n o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
57612\n setCoords(this, 1, 1, dx, dy, 0);\n } else {\n o.style.filter = E;\n setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);\n }\n } else {\n o.style.filter = E;\n skew.matrix = Str(matrix);\n skew.offset = matrix.offset();\n }\n if (oldt !== null) { // empty string value is true as well\n this._.transform = oldt;\n R._extractTransform(this, oldt);\n }\n return this;\n };\n elproto.rotate = function (deg, cx, cy) {\n if (this.removed) {\n return this;\n }\n if (deg == null) {\n return;\n }\n deg = Str(deg).split(separator);\n if (deg.length - 1) {\n cx = toFloat(deg[1]);\n cy = toFloat(deg[2]);\n }\n deg = toFloat(deg[0]);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n cx = bbox.x + bbox.width / 2;\n cy = bbox.y + bbox.height / 2;\n }\n this._.dirtyT = 1;\n this.transform(this._.transform.concat([[\"r\", deg, cx, cy]]));\n return this;\n };\n elproto.translate = function (dx, dy) {\n if (this.removed) {\n return this;\n }\n dx = Str(dx).split(separator);\n if (dx.length - 1) {\n dy = toFloat(dx[1]);\n }\n dx = toFloat(dx[0]) || 0;\n dy = +dy || 0;\n if (this._.bbox) {\n this._.bbox.x += dx;\n this._.bbox.y += dy;\n }\n this.transform(this._.transform.concat([[\"t\", dx, dy]]));\n return this;\n };\n elproto.scale = function (sx, sy, cx, cy) {\n if (this.removed) {\n return this;\n }\n sx = Str(sx).split(separator);\n if (sx.length - 1) {\n sy = toFloat(sx[1]);\n cx = toFloat(sx[2]);\n cy = toFloat(sx[3]);\n isNaN(cx) && (cx = null);\n isNaN(cy) && (cy = null);\n }\n sx = toFloat(sx[0]);\n (sy == null) && (sy = sx);\n (cy == null) && (cx = cy);\n if (cx == null || cy == null) {\n var bbox = this.getBBox(1);\n }\n cx = cx == null ? bbox.x + bbox.width / 2 : cx;\n cy = cy == null ? bbox.y + bbox.height / 2 : cy;\n\n this.transform(this._.transform.concat([[\"s\", sx, sy, cx, cy]]));\n this._.dirtyT = 1;\n return this;\n };\n elproto.hide = function () {\n !this.removed && (this.node.style.display = \"none\");\n return this;\n };\n elproto.show = function () {\n !this.removed && (this.node.style.display = E);\n return this;\n };\n // Needed to fix the vml setViewBox issues\n elproto.auxGetBBox = R.el.getBBox;\n elproto.getBBox = function(){\n var b = this.auxGetBBox();\n if (this.paper && this.paper._viewBoxShift)\n {\n var c = {};\n var z = 1/this.paper._viewBoxShift.scale;\n c.x = b.x - this.paper._viewBoxShift.dx;\n c.x *= z;\n c.y = b.y - this.paper._viewBoxShift.dy;\n c.y *= z;\n c.width = b.width * z;
57612\n c.height = b.height * z;\n c.x2 = c.x + c.width;\n c.y2 = c.y + c.height;\n return c;\n }\n return b;\n };\n elproto._getBBox = function () {\n if (this.removed) {\n return {};\n }\n return {\n x: this.X + (this.bbx || 0) - this.W / 2,\n y: this.Y - this.H,\n width: this.W,\n height: this.H\n };\n };\n elproto.remove = function () {\n if (this.removed || !this.node.parentNode) {\n return;\n }\n this.paper.__set__ && this.paper.__set__.exclude(this);\n R.eve.unbind(\"raphael.*.*.\" + this.id);\n R._tear(this, this.paper);\n this.node.parentNode.removeChild(this.node);\n this.shape && this.shape.parentNode.removeChild(this.shape);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n this.removed = true;\n };\n elproto.attr = function (name, value) {\n if (this.removed) {\n return this;\n }\n if (name == null) {\n var res = {};\n for (var a in this.attrs) if (this.attrs[has](a)) {\n res[a] = this.attrs[a];\n }\n res.gradient && res.fill == \"none\" && (res.fill = res.gradient) && delete res.gradient;\n res.transform = this._.transform;\n return res;\n }\n if (value == null && R.is(name, \"string\")) {\n if (name == fillString && this.attrs.fill == \"none\" && this.attrs.gradient) {\n return this.attrs.gradient;\n }\n var names = name.split(separator),\n out = {};\n for (var i = 0, ii = names.length; i < ii; i++) {\n name = names[i];\n if (name in this.attrs) {\n out[name] = this.attrs[name];\n } else if (R.is(this.paper.customAttributes[name], \"function\")) {\n out[name] = this.paper.customAttributes[name].def;\n } else {\n out[name] = R._availableAttrs[name];\n }\n }\n return ii - 1 ? out : out[names[0]];\n }\n if (this.attrs && value == null && R.is(name, \"array\")) {\n out = {};\n for (i = 0, ii = name.length; i < ii; i++) {\n out[name[i]] = this.attr(name[i]);\n }\n return out;\n }\n var params;\n if (value != null) {\n params = {};\n params[name] = value;\n }\n value == null && R.is(name, \"object\") && (params = name);\n for (var key in params) {\n eve(\"raphael.attr.\" + key + \".\" + this.id, this, params[key]);\n }\n if (params) {\n for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], \"function\")) {\n var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));\n this.attrs[key] = params[key];\n for (var subkey in par) if (par[has](subkey)) {\n params[subkey] = par[subkey];\n }\n }\n // this.paper.canvas.style.display = \"none\";\n if (params.text && this.type == \"text\") {\n this.textpath.string = params.text;\n }\n setFillAndStroke(this, params);\n // this.paper.canvas.style.display = E;\n }\n return this;\n };\n elproto.toFront = function () {\n !this.removed && this.node.parentNode.appendChild(this.node);\n this.paper && this.paper.top != this && R._tofront(this, this.paper);\n return this;\n };\n elproto.toBack = function () {\n if (this.removed) {\n return this;\n }\n if (this.node.parentNode.firstChild != this.node) {\n this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);\n R._toback(this, this.paper);\n }\n return this;\n };\n elproto.insertAfter = function (element) {\n if (this.removed) {\
57612n return this;\n }\n if (element.constructor == R.st.constructor) {\n element = element[element.length - 1];\n }\n if (element.node.nextSibling) {\n element.node.parentNode.insertBefore(this.node, element.node.nextSibling);\n } else {\n element.node.parentNode.appendChild(this.node);\n }\n R._insertafter(this, element, this.paper);\n return this;\n };\n elproto.insertBefore = function (element) {\n if (this.removed) {\n return this;\n }\n if (element.constructor == R.st.constructor) {\n element = element[0];\n }\n element.node.parentNode.insertBefore(this.node, element.node);\n R._insertbefore(this, element, this.paper);\n return this;\n };\n elproto.blur = function (size) {\n var s = this.node.runtimeStyle,\n f = s.filter;\n f = f.replace(blurregexp, E);\n if (+size !== 0) {\n this.attrs.blur = size;\n s.filter = f + S + ms + \".Blur(pixelradius=\" + (+size || 1.5) + \")\";\n s.margin = R.format(\"-{0}px 0 0 -{0}px\", round(+size || 1.5));\n } else {\n s.filter = f;\n s.margin = 0;\n delete this.attrs.blur;\n }\n return this;\n };\n\n R._engine.path = function (pathString, vml) {\n var el = createNode(\"shape\");\n el.style.cssText = cssDot;\n el.coordsize = zoom + S + zoom;\n el.coordorigin = vml.coordorigin;\n var p = new Element(el, vml),\n attr = {fill: \"none\", stroke: \"#000\"};\n pathString && (attr.path = pathString);\n p.type = \"path\";\n p.path = [];\n p.Path = E;\n setFillAndStroke(p, attr);\n vml.canvas && vml.canvas.appendChild(el);\n var skew = createNode(\"skew\");\n skew.on = true;\n el.appendChild(skew);\n p.skew = skew;\n p.transform(E);\n return p;\n };\n R._engine.rect = function (vml, x, y, w, h, r) {\n var path = R._rectPath(x, y, w, h, r),\n res = vml.path(path),\n a = res.attrs;\n res.X = a.x = x;\n res.Y = a.y = y;\n res.W = a.width = w;\n res.H = a.height = h;\n a.r = r;\n a.path = path;\n res.type = \"rect\";\n return res;\n };\n R._engine.ellipse = function (vml, x, y, rx, ry) {\n var res = vml.path(),\n a = res.attrs;\n res.X = x - rx;\n res.Y = y - ry;\n res.W = rx * 2;\n res.H = ry * 2;\n res.type = \"ellipse\";\n setFillAndStroke(res, {\n cx: x,\n cy: y,\n rx: rx,\n ry: ry\n });\n return res;\n };\n R._engine.circle = function (vml, x, y, r) {\n var res = vml.path(),\n a = res.attrs;\n res.X = x - r;\n res.Y = y - r;\n res.W = res.H = r * 2;\n res.type = \"circle\";\n setFillAndStroke(res, {\n cx: x,\n cy: y,\n r: r\n });\n return res;\n };\n R._engine.image = function (vml, src, x, y, w, h) {\n var path = R._rectPath(x, y, w, h),\n res = vml.path(path).attr({stroke: \"none\"}),\n a = res.attrs,\n node = res.node,\n fill = node.getElementsByTagName(fillString)[0];\n a.src = src;\n res.X = a.x = x;\n res.Y = a.y = y;\n res.W = a.width = w;\n res.H = a.height = h;\n a.path = path;\n res.type = \"image\";\n fill.parentNode == node && node.removeChild(fill);\n fill.rotate = true;\n fill.src = src;\n fill.type = \"tile\";\n res._.fillpos = [x, y];\n res._.fillsize = [w, h];\n node.appendChild(fill);\n setCoords(res, 1, 1, 0, 0, 0);\n return res;\n };\n R._engine.text = function (vml, x, y, text) {\n var el = createNode(\"shape\"),\n path = createNode(\"path\"),\n o = createNode(\"textpath\");\n x = x || 0;\n y = y || 0;\n text = text || \"\";\n path.v = R.format(\"m{0},{1}l{2},{1}
57612\", round(x * zoom), round(y * zoom), round(x * zoom) + 1);\n path.textpathok = true;\n o.string = Str(text);\n o.on = true;\n el.style.cssText = cssDot;\n el.coordsize = zoom + S + zoom;\n el.coordorigin = \"0 0\";\n var p = new Element(el, vml),\n attr = {\n fill: \"#000\",\n stroke: \"none\",\n font: R._availableAttrs.font,\n text: text\n };\n p.shape = el;\n p.path = path;\n p.textpath = o;\n p.type = \"text\";\n p.attrs.text = Str(text);\n p.attrs.x = x;\n p.attrs.y = y;\n p.attrs.w = 1;\n p.attrs.h = 1;\n setFillAndStroke(p, attr);\n el.appendChild(o);\n el.appendChild(path);\n vml.canvas.appendChild(el);\n var skew = createNode(\"skew\");\n skew.on = true;\n el.appendChild(skew);\n p.skew = skew;\n p.transform(E);\n return p;\n };\n R._engine.setSize = function (width, height) {\n var cs = this.canvas.style;\n this.width = width;\n this.height = height;\n width == +width && (width += \"px\");\n height == +height && (height += \"px\");\n cs.width = width;\n cs.height = height;\n cs.clip = \"rect(0 \" + width + \" \" + height + \" 0)\";\n if (this._viewBox) {\n R._engine.setViewBox.apply(this, this._viewBox);\n }\n return this;\n };\n R._engine.setViewBox = function (x, y, w, h, fit) {\n R.eve(\"raphael.setViewBox\", this, this._viewBox, [x, y, w, h, fit]);\n var paperSize = this.getSize(),\n width = paperSize.width,\n height = paperSize.height,\n H, W;\n if (fit) {\n H = height / h;\n W = width / w;\n if (w * H < width) {\n x -= (width - w * H) / 2 / H;\n }\n if (h * W < height) {\n y -= (height - h * W) / 2 / W;\n }\n }\n this._viewBox = [x, y, w, h, !!fit];\n this._viewBoxShift = {\n dx: -x,\n dy: -y,\n scale: paperSize\n };\n this.forEach(function (el) {\n el.transform(\"...\");\n });\n return this;\n };\n var createNode;\n R._engine.initWin = function (win) {\n var doc = win.document;\n if (doc.styleSheets.length < 31) {\n doc.createStyleSheet().addRule(\".rvml\", \"behavior:url(#default#VML)\");\n } else {\n // no more room, add to the existing one\n // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx\n doc.styleSheets[0].addRule(\".rvml\", \"behavior:url(#default#VML)\");\n }\n try {\n !doc.namespaces.rvml && doc.namespaces.add(\"rvml\", \"urn:schemas-microsoft-com:vml\");\n createNode = function (tagName) {\n return doc.createElement('<rvml:' + tagName + ' class=\"rvml\">');\n };\n } catch (e) {\n createNode = function (tagName) {\n return doc.createElement('<' + tagName + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">');\n };\n }\n };\n R._engine.initWin(R._g.win);\n R._engine.create = function () {\n var con = R._getContainer.apply(0, arguments),\n container = con.container,\n height = con.height,\n s,\n width = con.width,\n x = con.x,\n y = con.y;\n if (!container) {\n throw new Error(\"VML container not found.\");\n }\n var res = new R._Paper,\n c = res.canvas = R._g.doc.createElement(\"div\"),\n cs = c.style;\n x = x || 0;\n y = y || 0;\n width = width || 512;\n height = height || 342;\n res.width = width;\n res.height = height;\n width == +width && (width += \"px\");\n height == +height && (height += \"px\");\n res.coordsize = zoom * 1e3 + S + zoom * 1e3;\n res.coordorigin = \"0 0\";\n res.span = R._g.doc.createElement(\"span\");\n res.span.style.cssText = \"position:absolute;
57612left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\";\n c.appendChild(res.span);\n cs.cssText = R.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\", width, height);\n if (container == 1) {\n R._g.doc.body.appendChild(c);\n cs.left = x + \"px\";\n cs.top = y + \"px\";\n cs.position = \"absolute\";\n } else {\n if (container.firstChild) {\n container.insertBefore(c, container.firstChild);\n } else {\n container.appendChild(c);\n }\n }\n res.renderfix = function () {};\n return res;\n };\n R.prototype.clear = function () {\n R.eve(\"raphael.clear\", this);\n this.canvas.innerHTML = E;\n this.span = R._g.doc.createElement(\"span\");\n this.span.style.cssText = \"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\";\n this.canvas.appendChild(this.span);\n this.bottom = this.top = null;\n };\n R.prototype.remove = function () {\n R.eve(\"raphael.remove\", this);\n this.canvas.parentNode.removeChild(this.canvas);\n for (var i in this) {\n this[i] = typeof this[i] == \"function\" ? R._removedFactory(i) : null;\n }\n return true;\n };\n\n var setproto = R.st;\n for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {\n setproto[method] = (function (methodname) {\n return function () {\n var arg = arguments;\n return this.forEach(function (el) {\n el[methodname].apply(el, arg);\n });\n };\n })(method);\n }\n}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9kZXYvcmFwaGFlbC52bWwuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9SYXBoYWVsLy4vZGV2L3JhcGhhZWwudm1sLmpzP2JhZjAiXSwic291cmNlc0NvbnRlbnQiOlsiZGVmaW5lKFtcIi4vcmFwaGFlbC5jb3JlXCJdLCBmdW5jdGlvbihSKSB7XG4gICAgaWYgKFIgJiYgIVIudm1sKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaGFzID0gXCJoYXNPd25Qcm9wZXJ0eVwiLFxuICAgICAgICBTdHIgPSBTdHJpbmcsXG4gICAgICAgIHRvRmxvYXQgPSBwYXJzZUZsb2F0LFxuICAgICAgICBtYXRoID0gTWF0aCxcbiAgICAgICAgcm91bmQgPSBtYXRoLnJvdW5kLFxuICAgICAgICBtbWF4ID0gbWF0aC5tYXgsXG4gICAgICAgIG1taW4gPSBtYXRoLm1pbixcbiAgICAgICAgYWJzID0gbWF0aC5hYnMsXG4gICAgICAgIGZpbGxTdHJpbmcgPSBcImZpbGxcIixcbiAgICAgICAgc2VwYXJhdG9yID0gL1ssIF0rLyxcbiAgICAgICAgZXZlID0gUi5ldmUsXG4gICAgICAgIG1zID0gXCIgcHJvZ2lkOkRYSW1hZ2VUcmFuc2Zvcm0uTWljcm9zb2Z0XCIsXG4gICAgICAgIFMgPSBcIiBcIixcbiAgICAgICAgRSA9IFwiXCIsXG4gICAgICAgIG1hcCA9IHtNOiBcIm1cIiwgTDogXCJsXCIsIEM6IFwiY1wiLCBaOiBcInhcIiwgbTogXCJ0XCIsIGw6IFwiclwiLCBjOiBcInZcIiwgejogXCJ4XCJ9LFxuICAgICAgICBiaXRlcyA9IC8oW2NsbXpdKSw/KFteY2xtel0qKS9naSxcbiAgICAgICAgYmx1cnJlZ2V4cCA9IC8gcHJvZ2lkOlxcUytCbHVyXFwoW15cXCldK1xcKS9nLFxuICAgICAgICB2YWwgPSAvLT9bXixcXHMtXSsvZyxcbiAgICAgICAgY3NzRG90ID0gXCJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjA7dG9wOjA7d2lkdGg6MXB4O2hlaWdodDoxcHg7YmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTClcIixcbiAgICAgICAgem9vbSA9IDIxNjAwLFxuICAgICAgICBwYXRoVHlwZXMgPSB7cGF0aDogMSwgcmVjdDogMSwgaW1hZ2U6IDF9LFxuICAgICAgICBvdmFsVHlwZXMgPSB7Y2lyY2xlOiAxLCBlbGxpcHNlOiAxfSxcbiAgICAgICAgcGF0aDJ2bWwgPSBmdW5jdGlvbiAocGF0aCkge1xuICAgICAgICAgICAgdmFyIHRvdGFsID0gIC9bYWhxc3R2XS9pZyxcbiAgICAgICAgICAgICAgICBjb21tYW5kID0gUi5fcGF0aFRvQWJzb2x1dGU7XG4gICAgICAgICAgICBTdHIocGF0aCkubWF0Y2godG90YWwpICYmIChjb21tYW5kID0gUi5fcGF0aDJjdXJ2ZSk7XG4gICAgICAgICAgICB0b3RhbCA9IC9bY2xtel0vZztcbiAgICAgICAgICAgIGlmIChjb21tYW5kID09IFIuX3BhdGhUb0Fic29sdXRlICYmICFTdHIocGF0aCkubWF0Y2godG90YWwpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IFN0cihwYXRoKS5yZXBsYWNlKGJpdGVzLCBmdW5jdGlvbiAoYWxsLCBjb21tYW5kLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxzID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBpc01vdmUgPSBjb21tYW5kLnRvTG93ZXJDYXNlKCkgPT0gXCJtXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXMgPSBtYXBbY29tbWFuZF07XG4gICAgICAgICAgICAgICAgICAgIGFyZ3MucmVwbGFjZSh2YWwsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTW92ZSAmJi
57612B2YWxzLmxlbmd0aCA9PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzICs9IHZhbHMgKyBtYXBbY29tbWFuZCA9PSBcIm1cIiA/IFwibFwiIDogXCJMXCJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHMucHVzaChyb3VuZCh2YWx1ZSAqIHpvb20pKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXMgKyB2YWxzO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcGEgPSBjb21tYW5kKHBhdGgpLCBwLCByO1xuICAgICAgICAgICAgcmVzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBwYS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcCA9IHBhW2ldO1xuICAgICAgICAgICAgICAgIHIgPSBwYVtpXVswXS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHIgPT0gXCJ6XCIgJiYgKHIgPSBcInhcIik7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDEsIGpqID0gcC5sZW5ndGg7IGogPCBqajsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHIgKz0gcm91bmQocFtqXSAqIHpvb20pICsgKGogIT0gamogLSAxID8gXCIsXCIgOiBFKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzLnB1c2gocik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzLmpvaW4oUyk7XG4gICAgICAgIH0sXG4gICAgICAgIGNvbXBlbnNhdGlvbiA9IGZ1bmN0aW9uIChkZWcsIGR4LCBkeSkge1xuICAgICAgICAgICAgdmFyIG0gPSBSLm1hdHJpeCgpO1xuICAgICAgICAgICAgbS5yb3RhdGUoLWRlZywgLjUsIC41KTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZHg6IG0ueChkeCwgZHkpLFxuICAgICAgICAgICAgICAgIGR5OiBtLnkoZHgsIGR5KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0Q29vcmRzID0gZnVuY3Rpb24gKHAsIHN4LCBzeSwgZHgsIGR5LCBkZWcpIHtcbiAgICAgICAgICAgIHZhciBfID0gcC5fLFxuICAgICAgICAgICAgICAgIG0gPSBwLm1hdHJpeCxcbiAgICAgICAgICAgICAgICBmaWxscG9zID0gXy5maWxscG9zLFxuICAgICAgICAgICAgICAgIG8gPSBwLm5vZGUsXG4gICAgICAgICAgICAgICAgcyA9IG8uc3R5bGUsXG4gICAgICAgICAgICAgICAgeSA9IDEsXG4gICAgICAgICAgICAgICAgZmxpcCA9IFwiXCIsXG4gICAgICAgICAgICAgICAgZHhkeSxcbiAgICAgICAgICAgICAgICBreCA9IHpvb20gLyBzeCxcbiAgICAgICAgICAgICAgICBreSA9IHpvb20gLyBzeTtcbiAgICAgICAgICAgIHMudmlzaWJpbGl0eSA9IFwiaGlkZGVuXCI7XG4gICAgICAgICAgICBpZiAoIXN4IHx8ICFzeSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG8uY29vcmRzaXplID0gYWJzKGt4KSArIFMgKyBhYnMoa3kpO1xuICAgICAgICAgICAgcy5yb3RhdGlvbiA9IGRlZyAqIChzeCAqIHN5IDwgMCA/IC0xIDogMSk7XG4gICAgICAgICAgICBpZiAoZGVnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGMgPSBjb21wZW5zYXRpb24oZGVnLCBkeCwgZHkpO1xuICAgICAgICAgICAgICAgIGR4ID0gYy5keDtcbiAgICAgICAgICAgICAgICBkeSA9IGMuZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzeCA8IDAgJiYgKGZsaXAgKz0gXCJ4XCIpO1xuICAgICAgICAgICAgc3kgPCAwICYmIChmbGlwICs9IFwiIHlcIikgJiYgKHkgPSAtMSk7XG4gICAgICAgICAgICBzLmZsaXAgPSBmbGlwO1xuICAgICAgICAgICAgby5jb29yZG9yaWdpbiA9IChkeCAqIC1reCkgKyBTICsgKGR5ICogLWt5KTtcbiAgICAgICAgICAgIGlmIChmaWxscG9zIHx8IF8uZmlsbHNpemUpIHtcbiAgICAgICAgICAgICAgICB2Y
57612XIgZmlsbCA9IG8uZ2V0RWxlbWVudHNCeVRhZ05hbWUoZmlsbFN0cmluZyk7XG4gICAgICAgICAgICAgICAgZmlsbCA9IGZpbGwgJiYgZmlsbFswXTtcbiAgICAgICAgICAgICAgICBvLnJlbW92ZUNoaWxkKGZpbGwpO1xuICAgICAgICAgICAgICAgIGlmIChmaWxscG9zKSB7XG4gICAgICAgICAgICAgICAgICAgIGMgPSBjb21wZW5zYXRpb24oZGVnLCBtLngoZmlsbHBvc1swXSwgZmlsbHBvc1sxXSksIG0ueShmaWxscG9zWzBdLCBmaWxscG9zWzFdKSk7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwucG9zaXRpb24gPSBjLmR4ICogeSArIFMgKyBjLmR5ICogeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKF8uZmlsbHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5zaXplID0gXy5maWxsc2l6ZVswXSAqIGFicyhzeCkgKyBTICsgXy5maWxsc2l6ZVsxXSAqIGFicyhzeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG8uYXBwZW5kQ2hpbGQoZmlsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzLnZpc2liaWxpdHkgPSBcInZpc2libGVcIjtcbiAgICAgICAgfTtcbiAgICBSLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gIFwiWW91ciBicm93c2VyIGRvZXNuXFx1MjAxOXQgc3VwcG9ydCBTVkcuIEZhbGxpbmcgZG93biB0byBWTUwuXFxuWW91IGFyZSBydW5uaW5nIFJhcGhhXFx4ZWJsIFwiICsgdGhpcy52ZXJzaW9uO1xuICAgIH07XG4gICAgdmFyIGFkZEFycm93ID0gZnVuY3Rpb24gKG8sIHZhbHVlLCBpc0VuZCkge1xuICAgICAgICB2Y
57612XIgdmFsdWVzID0gU3RyKHZhbHVlKS50b0xvd2VyQ2FzZSgpLnNwbGl0KFwiLVwiKSxcbiAgICAgICAgICAgIHNlID0gaXNFbmQgPyBcImVuZFwiIDogXCJzdGFydFwiLFxuICAgICAgICAgICAgaSA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgICB0eXBlID0gXCJjbGFzc2ljXCIsXG4gICAgICAgICAgICB3ID0gXCJtZWRpdW1cIixcbiAgICAgICAgICAgIGggPSBcIm1lZGl1bVwiO1xuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHZhbHVlc1tpXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgXCJibG9ja1wiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJjbGFzc2ljXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIm92YWxcIjpcbiAgICAgICAgICAgICAgICBjYXNlIFwiZGlhbW9uZFwiOlxuICAgICAgICAgICAgICAgIGNhc2UgXCJvcGVuXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIm5vbmVcIjpcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcIndpZGVcIjpcbiAgICAgICAgICAgICAgICBjYXNlIFwibmFycm93XCI6IGggPSB2YWx1ZXNbaV07IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJsb25nXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcInNob3J0XCI6IHcgPSB2YWx1ZXNbaV07IGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBzdHJva2UgPSBvLm5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdHJva2VcIilbMF07XG4gICAgICAgIHN0cm9rZVtzZSArIFwiYXJyb3dcIl0gPSB0eXBlO1xuICAgICAgICBzdHJva2Vbc2UgKyBcImFycm93bGVuZ3RoXCJdID0gdztcbiAgICAgICAgc3Ryb2tlW3NlICsgXCJhcnJvd3dpZHRoXCJdID0gaDtcbiAgICB9LFxuICAgIHNldEZpbGxBbmRTdHJva2UgPSBmdW5jdGlvbiAobywgcGFyYW1zKSB7XG4gICAgICAgIC8vIG8ucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgby5hdHRycyA9IG8uYXR0cnMgfHwge307XG4gICAgICAgIHZhciBub2RlID0gby5ub2RlLFxuICAgICAgICAgICAgYSA9IG8uYXR0cnMsXG4gICAgICAgICAgICBzID0gbm9kZS5zdHlsZSxcbiAgICAgICAgICAgIHh5LFxuICAgICAgICAgICAgbmV3cGF0aCA9IHBhdGhUeXBlc1tvLnR5cGVdICYmIChwYXJhbXMueCAhPSBhLnggfHwgcGFyYW1zLnkgIT0gYS55IHx8IHBhcmFtcy53aWR0aCAhPSBhLndpZHRoIHx8IHBhcmFtcy5oZWlnaHQgIT0gYS5oZWlnaHQgfHwgcGFyYW1zLmN4ICE9IGEuY3ggfHwgcGFyYW1zLmN5ICE9IGEuY3kgfHwgcGFyYW1zLnJ4ICE9IGEucnggfHwgcGFyYW1zLnJ5ICE9IGEucnkgfHwgcGFyYW1zLnIgIT0gYS5yKSxcbiAgICAgICAgICAgIGlzT3ZhbCA9IG92YWxUeXBlc1tvLnR5cGVdICYmIChhLmN4ICE9IHBhcmFtcy5jeCB8fCBhLmN5ICE9IHBhcmFtcy5jeSB8fCBhLnIgIT0gcGFyYW1zLnIgfHwgYS5yeCAhPSBwYXJhbXMucnggfHwgYS5yeSAhPSBwYXJhbXMucnkpLFxuICAgICAgICAgICAgcmVzID0gbztcblxuXG4gICAgICAgIGZvciAodmFyIHBhciBpbiBwYXJhbXMpIGlmIChwYXJhbXNbaGFzXShwYXIpKSB7XG4gICAgICAgICAgICBhW3Bhcl0gPSBwYXJhbXNbcGFyXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV3cGF0aCkge1xuICAgICAgICAgICAgYS5wYXRoID0gUi5fZ2V0UGF0aFtvLnR5cGVdKG8pO1xuICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgfVxuICAgICAgICBwYXJhbXMuaHJlZiAmJiAobm9kZS5ocmVmID0gcGFyYW1zLmhyZWYpO1xuICAgICAgICBwYXJhbXMudGl0bGUgJiYgKG5vZGUudGl0bGUgPSBwYXJhbXMudGl0bGUpO1xuICAgICAgICBwYXJhbXMudGFyZ2V0ICYmIChub2RlLnRhcmdldCA9IHBhcmFtcy50YXJnZXQpO1xuICAgICAgICBwYXJhbXMuY3Vyc29yICYmIChzLmN1cnNvciA9IHBhcmFtcy5jdXJzb3IpO1xuICAgICAgICBcImJsdXJcIiBpbiBwYXJhbXMgJiYgby5ibHVyKHBhcmFtcy5ibHVyKTtcbiAgICAgICAgaWYgKHBhcmFtcy5wYXRoICYmIG8udHlwZSA9PSBcInBhdGhcIiB8fCBuZXdwYXRoKSB7XG4gICAgICAgICAgICBub2RlLnBhdGggPSBwYXRoMnZtbCh+U3RyKGEucGF0aCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKFwiclwiKSA/IFIuX3BhdGhUb0Fic29sdXRlKGEucGF0aCkgOiBhLnBhdGgpO1xuICAgICAgICAgICAgby5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgIGlmIChvLnR5cGUgPT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgICAgICAgby5fLmZpbGxwb3MgPSBbYS54LCBhLnldO1xuICAgICAgICAgICAgICAgIG8uXy5maWxsc2l6ZSA9IFthLndpZHRoLCBhLmhlaWdodF07XG4gICAgICAgICAgICAgICAgc2V0Q29vcmRzKG8sIDEsIDEsIDAsIDAsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFwidHJhbnNmb3JtXCIgaW4gcGFyYW1zICYmIG8udHJhbnNmb3JtKHBhcmFtcy50cmFuc2Zvcm0pO1xuICAgICAgICBpZiAoaXNPdmFsKSB7XG4gICAgICAgICAgICB2Y
57612XIgY3ggPSArYS5jeCxcbiAgICAgICAgICAgICAgICBjeSA9ICthLmN5LFxuICAgICAgICAgICAgICAgIHJ4ID0gK2EucnggfHwgK2EuciB8fCAwLFxuICAgICAgICAgICAgICAgIHJ5ID0gK2EucnkgfHwgK2EuciB8fCAwO1xuICAgICAgICAgICAgbm9kZS5wYXRoID0gUi5mb3JtYXQoXCJhcnswfSx7MX0sezJ9LHszfSx7NH0sezF9LHs0fSx7MX14XCIsIHJvdW5kKChjeCAtIHJ4KSAqIHpvb20pLCByb3VuZCgoY3kgLSByeSkgKiB6b29tKSwgcm91bmQoKGN4ICsgcngpICogem9vbSksIHJvdW5kKChjeSArIHJ5KSAqIHpvb20pLCByb3VuZChjeCAqIHpvb20pKTtcbiAgICAgICAgICAgIG8uXy5kaXJ0eSA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFwiY2xpcC1yZWN0XCIgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICB2YXIgcmVjdCA9IFN0cihwYXJhbXNbXCJjbGlwLXJlY3RcIl0pLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgICAgICBpZiAocmVjdC5sZW5ndGggPT0gNCkge1xuICAgICAgICAgICAgICAgIHJlY3RbMl0gPSArcmVjdFsyXSArICgrcmVjdFswXSk7XG4gICAgICAgICAgICAgICAgcmVjdFszXSA9ICtyZWN0WzNdICsgKCtyZWN0WzFdKTtcbiAgICAgICAgICAgICAgICB2YXIgZGl2ID0gbm9kZS5jbGlwUmVjdCB8fCBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgICAgICAgICBkc3R5bGUgPSBkaXYuc3R5bGU7XG4gICAgICAgICAgICAgICAgZHN0eWxlLmNsaXAgPSBSLmZvcm1hdChcInJlY3QoezF9cHggezJ9cHggezN9cHggezB9cHgpXCIsIHJlY3QpO1xuICAgICAgICAgICAgICAgIGlmICghbm9kZS5jbGlwUmVjdCkge1xuICAgICAgICAgICAgICAgICAgICBkc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS50b3AgPSAwO1xuICAgICAgICAgICAgICAgICAgICBkc3R5bGUubGVmdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS53aWR0aCA9IG8ucGFwZXIud2lkdGggKyBcInB4XCI7XG4gICAgICAgICAgICAgICAgICAgIGRzdHlsZS5oZWlnaHQgPSBvLnBhcGVyLmhlaWdodCArIFwicHhcIjtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShkaXYsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBkaXYuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUuY2xpcFJlY3QgPSBkaXY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFwYXJhbXNbXCJjbGlwLXJlY3RcIl0pIHtcbiAgICAgICAgICAgICAgICBub2RlLmNsaXBSZWN0ICYmIChub2RlLmNsaXBSZWN0LnN0eWxlLmNsaXAgPSBcImF1dG9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG8udGV4dHBhdGgpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0cGF0aFN0eWxlID0gby50ZXh0cGF0aC5zdHlsZTtcbiAgICAgICAgICAgIHBhcmFtcy5mb250ICYmICh0ZXh0cGF0aFN0eWxlLmZvbnQgPSBwYXJhbXMuZm9udCk7XG4gICAgICAgICAgICBwYXJhbXNbXCJmb250LWZhbWlseVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250RmFtaWx5ID0gJ1wiJyArIHBhcmFtc1tcImZvbnQtZmFtaWx5XCJdLnNwbGl0KFwiLFwiKVswXS5yZXBsYWNlKC9eWydcIl0rfFsnXCJdKyQvZywgRSkgKyAnXCInKTtcbiAgICAgICAgICAgIHBhcmFtc1tcImZvbnQtc2l6ZVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250U2l6ZSA9IHBhcmFtc1tcImZvbnQtc2l6ZVwiXSk7XG4gICAgICAgICAgICBwYXJhbXNbXCJmb250LXdlaWdodFwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250V2VpZ2h0ID0gcGFyYW1zW1wiZm9udC13ZWlnaHRcIl0pO1xuICAgICAgICAgICAgcGFyYW1zW1wiZm9udC1zdHlsZVwiXSAmJiAodGV4dHBhdGhTdHlsZS5mb250U3R5bGUgPSBwYXJhbXNbXCJmb250LXN0eWxlXCJdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXCJhcnJvdy1zdGFydFwiIGluIHBhcmFtcykge1xuICAgICAgICAgICAgYWRkQXJyb3cocmVzLCBwYXJhbXNbXCJhcnJvdy1zdGFydFwiXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFwiYXJyb3ctZW5kXCIgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBhZGRBcnJvdyhyZXMsIHBhcmFtc1tcImFycm93LWVuZFwiXSwgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy5vcGFjaXR5ICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtcy5maWxsICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtcy5zcmMgIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zLnN0cm9rZSAhPSBudWxsIHx8XG4gICAgICAgICAgICBwYXJhbXNbXCJzdHJva2Utd2lkdGhcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW9wYWNpdHlcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wiZmlsbC1vcGFjaXR5XCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1kYXNoYXJyYXlcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gIT0gbnVsbCB8fFxuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLWxpbmVqb2luXCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBmaWxsID0gbm9kZS5nZXRFbGVtZW50c0J5VGFnTmFtZShmaWxsU3RyaW5nKSxcbiAgICAgICAgICAgICAgICBuZXdmaWxsID0gZmFsc2U7XG4gICAgICAgICAgICBmaWxsID0gZmlsbCAmJiBmaWxsWzBdO1xuICAgICAgICAgICAgIWZpbGwgJiYgKG5ld2ZpbGwgPSBmaWxsID0gY3JlYXRlTm9kZShmaWxsU3RyaW5nKSk7XG4gICAgICAgICAgICBpZiAoby50eXBlID09IFwiaW1hZ2VcIiAmJiBwYXJhbXMuc3JjKSB7XG4gICAgICAgICAgICAgICAgZmlsbC5zcmMgPSBwYXJhbXMuc3JjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyYW1zLmZpbGwgJiYgKGZpbGwub24gPSB0cnVlKTtcbiAgICAgICAgICAgIGlmIChmaWxsLm9uID09IG51bGwgfHwgcGFyYW1zLmZpbGwgPT0gXCJub25lXCIgfHwgcGFyYW1zLmZpbGwgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmaWxsLm9uID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlsbC5vbiAmJiBwYXJhbXMuZmlsbCkge1xuICAgICAgICAgICAgICAgI
57612HZhciBpc1VSTCA9IFN0cihwYXJhbXMuZmlsbCkubWF0Y2goUi5fSVNVUkwpO1xuICAgICAgICAgICAgICAgIGlmIChpc1VSTCkge1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnBhcmVudE5vZGUgPT0gbm9kZSAmJiBub2RlLnJlbW92ZUNoaWxkKGZpbGwpO1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnJvdGF0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwuc3JjID0gaXNVUkxbMV07XG4gICAgICAgICAgICAgICAgICAgIGZpbGwudHlwZSA9IFwidGlsZVwiO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYmJveCA9IG8uZ2V0QkJveCgxKTtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5wb3NpdGlvbiA9IGJib3gueCArIFMgKyBiYm94Lnk7XG4gICAgICAgICAgICAgICAgICAgIG8uXy5maWxscG9zID0gW2Jib3gueCwgYmJveC55XTtcblxuICAgICAgICAgICAgICAgICAgICBSLl9wcmVsb2FkKGlzVVJMWzFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvLl8uZmlsbHNpemUgPSBbdGhpcy5vZmZzZXRXaWR0aCwgdGhpcy5vZmZzZXRIZWlnaHRdO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmaWxsLmNvbG9yID0gUi5nZXRSR0IocGFyYW1zLmZpbGwpLmhleDtcbiAgICAgICAgICAgICAgICAgICAgZmlsbC5zcmMgPSBFO1xuICAgICAgICAgICAgICAgICAgICBmaWxsLnR5cGUgPSBcInNvbGlkXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmIChSLmdldFJHQihwYXJhbXMuZmlsbCkuZXJyb3IgJiYgKHJlcy50eXBlIGluIHtjaXJjbGU6IDEsIGVsbGlwc2U6IDF9IHx8IFN0cihwYXJhbXMuZmlsbCkuY2hhckF0KCkgIT0gXCJyXCIpICYmIGFkZEdyYWRpZW50RmlsbChyZXMsIHBhcmFtcy5maWxsLCBmaWxsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYS5maWxsID0gXCJub25lXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBhLmdyYWRpZW50ID0gcGFyYW1zLmZpbGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsLnJvdGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFwiZmlsbC1vcGFjaXR5XCIgaW4gcGFyYW1zIHx8IFwib3BhY2l0eVwiIGluIHBhcmFtcykge1xuICAgICAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gKCgrYVtcImZpbGwtb3BhY2l0eVwiXSArIDEgfHwgMikgLSAxKSAqICgoK2Eub3BhY2l0eSArIDEgfHwgMikgLSAxKSAqICgoK1IuZ2V0UkdCKHBhcmFtcy5maWxsKS5vICsgMSB8fCAyKSAtIDEpO1xuICAgICAgICAgICAgICAgIG9wYWNpdHkgPSBtbWluKG1tYXgob3BhY2l0eSwgMCksIDEpO1xuICAgICAgICAgICAgICAgIGZpbGwub3BhY2l0eSA9IG9wYWNpdHk7XG4gICAgICAgICAgICAgICAgaWYgKGZpbGwuc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGwuY29sb3IgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGZpbGwpO1xuICAgICAgICAgICAgdmFyIHN0cm9rZSA9IChub2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwic3Ryb2tlXCIpICYmIG5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJzdHJva2VcIilbMF0pLFxuICAgICAgICAgICAgbmV3c3Ryb2tlID0gZmFsc2U7XG4gICAgICAgICAgICAhc3Ryb2tlICYmIChuZXdzdHJva2UgPSBzdHJva2UgPSBjcmVhdGVOb2RlKFwic3Ryb2tlXCIpKTtcbiAgICAgICAgICAgIGlmICgocGFyYW1zLnN0cm9rZSAmJiBwYXJhbXMuc3Ryb2tlICE9IFwibm9uZVwiKSB8fFxuICAgICAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSB8fFxuICAgICAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1vcGFjaXR5XCJdICE9IG51bGwgfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtZGFzaGFycmF5XCJdIHx8XG4gICAgICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gfHxcbiAgICAgICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWNhcFwiXSkge1xuICAgICAgICAgICAgICAgIHN0cm9rZS5vbiA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAocGFyYW1zLnN0cm9rZSA9PSBcIm5vbmVcIiB8fCBwYXJhbXMuc3Ryb2tlID09PSBudWxsIHx8IHN0cm9rZS5vbiA9PSBudWxsIHx8IHBhcmFtcy5zdHJva2UgPT0gMCB8fCBwYXJhbXNbXCJzdHJva2Utd2lkdGhcIl0gPT0gMCkgJiYgKHN0cm9rZS5vbiA9IGZhbHNlKTtcbiAgICAgICAgICAgIHZhciBzdHJva2VDb2xvciA9IFIuZ2V0UkdCKHBhcmFtcy5zdHJva2UpO1xuICAgICAgICAgICAgc3Ryb2tlLm9uICYmIHBhcmFtcy5zdHJva2UgJiYgKHN0cm9rZS5jb2xvciA9IHN0cm9rZUNvbG9yLmhleCk7XG4gICAgICAgICAgICBvcGFjaXR5ID0gKCgrYVtcInN0cm9rZS1vcGFjaXR5XCJdICsgMSB8fCAyKSAtIDEpICogKCgrYS5vcGFjaXR5ICsgMSB8fCAyKSAtIDEpICogKCgrc3Ryb2tlQ29sb3IubyArIDEgfHwgMikgLSAxKTtcbiAgICAgICAgICAgIHZhciB3aWR0aCA9ICh0b0Zsb2F0KHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSkgfHwgMSkgKiAuNzU7XG4gICAgICAgICAgICBvcGFjaXR5ID0gbW1pbihtbWF4KG9wYWNpdHksIDApLCAxKTtcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS13aWR0aFwiXSA9PSBudWxsICYmICh3aWR0aCA9IGFbXCJzdHJva2Utd2lkdGhcIl0pO1xuICAgICAgICAgICAgcGFyYW1zW1wic3Ryb2tlLXdpZHRoXCJdICYmIChzdHJva2Uud2VpZ2h0ID0gd2lkdGgpO1xuICAgICAgICAgICAgd2lkdGggJiYgd2lkdGggPCAxICYmIChvcGFjaXR5ICo9IHdpZHRoKSAmJiAoc3Ryb2tlLndlaWdodCA9IDEpO1xuICAgICAgICAgICAgc3Ryb2tlLm9wYWNpdHkgPSBvcGFjaXR5O1xuXG4gICAgICAgICAgICBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gJiYgKHN0cm9rZS5qb2luc3R5bGUgPSBwYXJhbXNbXCJzdHJva2UtbGluZWpvaW5cIl0gfHwgXCJtaXRlclwiKTtcbiAgICAgICAgICAgI
57612HN0cm9rZS5taXRlcmxpbWl0ID0gcGFyYW1zW1wic3Ryb2tlLW1pdGVybGltaXRcIl0gfHwgODtcbiAgICAgICAgICAgIHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdICYmIChzdHJva2UuZW5kY2FwID0gcGFyYW1zW1wic3Ryb2tlLWxpbmVjYXBcIl0gPT0gXCJidXR0XCIgPyBcImZsYXRcIiA6IHBhcmFtc1tcInN0cm9rZS1saW5lY2FwXCJdID09IFwic3F1YXJlXCIgPyBcInNxdWFyZVwiIDogXCJyb3VuZFwiKTtcbiAgICAgICAgICAgIGlmIChcInN0cm9rZS1kYXNoYXJyYXlcIiBpbiBwYXJhbXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGFzaGFycmF5ID0ge1xuICAgICAgICAgICAgICAgICAgICBcIi1cIjogXCJzaG9ydGRhc2hcIixcbiAgICAgICAgICAgICAgICAgICAgXCIuXCI6IFwic2hvcnRkb3RcIixcbiAgICAgICAgICAgICAgICAgICAgXCItLlwiOiBcInNob3J0ZGFzaGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0uLlwiOiBcInNob3J0ZGFzaGRvdGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi4gXCI6IFwiZG90XCIsXG4gICAgICAgICAgICAgICAgICAgIFwiLSBcIjogXCJkYXNoXCIsXG4gICAgICAgICAgICAgICAgICAgIFwiLS1cIjogXCJsb25nZGFzaFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0gLlwiOiBcImRhc2hkb3RcIixcbiAgICAgICAgICAgICAgICAgICAgXCItLS5cIjogXCJsb25nZGFzaGRvdFwiLFxuICAgICAgICAgICAgICAgICAgICBcIi0tLi5cIjogXCJsb25nZGFzaGRvdGRvdFwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBzdHJva2UuZGFzaHN0eWxlID0gZGFzaGFycmF5W2hhc10ocGFyYW1zW1wic3Ryb2tlLWRhc2hhcnJheVwiXSkgPyBkYXNoYXJyYXlbcGFyYW1zW1wic3Ryb2tlLWRhc2hhcnJheVwiXV0gOiBFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV3c3Ryb2tlICYmIG5vZGUuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzLnR5cGUgPT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgICAgIHJlcy5wYXBlci5jYW52YXMuc3R5bGUuZGlzcGxheSA9IEU7XG4gICAgICAgICAgICB2Y
57612XIgc3BhbiA9IHJlcy5wYXBlci5zcGFuLFxuICAgICAgICAgICAgICAgIG0gPSAxMDAsXG4gICAgICAgICAgICAgICAgZm9udFNpemUgPSBhLmZvbnQgJiYgYS5mb250Lm1hdGNoKC9cXGQrKD86XFwuXFxkKik/KD89cHgpLyk7XG4gICAgICAgICAgICBzID0gc3Bhbi5zdHlsZTtcbiAgICAgICAgICAgIGEuZm9udCAmJiAocy5mb250ID0gYS5mb250KTtcbiAgICAgICAgICAgIGFbXCJmb250LWZhbWlseVwiXSAmJiAocy5mb250RmFtaWx5ID0gYVtcImZvbnQtZmFtaWx5XCJdKTtcbiAgICAgICAgICAgIGFbXCJmb250LXdlaWdodFwiXSAmJiAocy5mb250V2VpZ2h0ID0gYVtcImZvbnQtd2VpZ2h0XCJdKTtcbiAgICAgICAgICAgIGFbXCJmb250LXN0eWxlXCJdICYmIChzLmZvbnRTdHlsZSA9IGFbXCJmb250LXN0eWxlXCJdKTtcbiAgICAgICAgICAgIGZvbnRTaXplID0gdG9GbG9hdChhW1wiZm9udC1zaXplXCJdIHx8IGZvbnRTaXplICYmIGZvbnRTaXplWzBdKSB8fCAxMDtcbiAgICAgICAgICAgIHMuZm9udFNpemUgPSBmb250U2l6ZSAqIG0gKyBcInB4XCI7XG4gICAgICAgICAgICByZXMudGV4dHBhdGguc3RyaW5nICYmIChzcGFuLmlubmVySFRNTCA9IFN0cihyZXMudGV4dHBhdGguc3RyaW5nKS5yZXBsYWNlKC88L2csIFwiJiM2MDtcIikucmVwbGFjZSgvJi9nLCBcIiYjMzg7XCIpLnJlcGxhY2UoL1xcbi9nLCBcIjxicj5cIikpO1xuICAgICAgICAgICAgdmFyIGJyZWN0ID0gc3Bhbi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHJlcy5XID0gYS53ID0gKGJyZWN0LnJpZ2h0IC0gYnJlY3QubGVmdCkgLyBtO1xuICAgICAgICAgICAgcmVzLkggPSBhLmggPSAoYnJlY3QuYm90dG9tIC0gYnJlY3QudG9wKSAvIG07XG4gICAgICAgICAgICAvLyByZXMucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIHJlcy5YID0gYS54O1xuICAgICAgICAgICAgcmVzLlkgPSBhLnkgKyByZXMuSCAvIDI7XG5cbiAgICAgICAgICAgIChcInhcIiBpbiBwYXJhbXMgfHwgXCJ5XCIgaW4gcGFyYW1zKSAmJiAocmVzLnBhdGgudiA9IFIuZm9ybWF0KFwibXswfSx7MX1sezJ9LHsxfVwiLCByb3VuZChhLnggKiB6b29tKSwgcm91bmQoYS55ICogem9vbSksIHJvdW5kKGEueCAqIHpvb20pICsgMSkpO1xuICAgICAgICAgICAgdmFyIGRpcnR5YXR0cnMgPSBbXCJ4XCIsIFwieVwiLCBcInRleHRcIiwgXCJmb250XCIsIFwiZm9udC1mYW1pbHlcIiwgXCJmb250LXdlaWdodFwiLCBcImZvbnQtc3R5bGVcIiwgXCJmb250LXNpemVcIl07XG4gICAgICAgICAgICBmb3IgKHZhciBkID0gMCwgZGQgPSBkaXJ0eWF0dHJzLmxlbmd0aDsgZCA8IGRkOyBkKyspIGlmIChkaXJ0eWF0dHJzW2RdIGluIHBhcmFtcykge1xuICAgICAgICAgICAgICAgIHJlcy5fLmRpcnR5ID0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGV4dC1hbmNob3IgZW11bGF0aW9uXG4gICAgICAgICAgICBzd2l0Y2ggKGFbXCJ0ZXh0LWFuY2hvclwiXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgXCJzdGFydFwiOlxuICAgICAgICAgICAgICAgICAgICByZXMudGV4dHBhdGguc3R5bGVbXCJ2LXRleHQtYWxpZ25cIl0gPSBcImxlZnRcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IHJlcy5XIC8gMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgICAgICAgICAgIHJlcy50ZXh0cGF0aC5zdHlsZVtcInYtdGV4dC1hbGlnblwiXSA9IFwicmlnaHRcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IC1yZXMuVyAvIDI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVzLnRleHRwYXRoLnN0eWxlW1widi10ZXh0LWFsaWduXCJdID0gXCJjZW50ZXJcIjtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmJieCA9IDA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMudGV4dHBhdGguc3R5bGVbXCJ2LXRleHQta2VyblwiXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzLnBhcGVyLmNhbnZhcy5zdHlsZS5kaXNwbGF5ID0gRTtcbiAgICB9LFxuICAgIGFkZEdyYWRpZW50RmlsbCA9IGZ1bmN0aW9uIChvLCBncmFkaWVudCwgZmlsbCkge1xuICAgICAgICBvLmF0dHJzID0gby5hdHRycyB8fCB7fTtcbiAgICAgICAgdmFyIGF0dHJzID0gby5hdHRycyxcbiAgICAgICAgICAgIHBvdyA9IE1hdGgucG93LFxuICAgICAgICAgICAgb3BhY2l0eSxcbiAgICAgICAgICAgIG9pbmRleCxcbiAgICAgICAgICAgIHR5cGUgPSBcImxpbmVhclwiLFxuICAgICAgICAgICAgZnhmeSA9IFwiLjUgLjVcIjtcbiAgICAgICAgby5hdHRycy5ncmFkaWVudCA9IGdyYWRpZW50O1xuICAgICAgICBncmFkaWVudCA9IFN0cihncmFkaWVudCkucmVwbGFjZShSLl9yYWRpYWxfZ3JhZGllbnQsIGZ1bmN0aW9uIChhbGwsIGZ4LCBmeSkge1xuICAgICAgICAgICAgdHlwZSA9IFwicmFkaWFsXCI7XG4gICAgICAgICAgICBpZiAoZnggJiYgZnkpIHtcbiAgICAgICAgICAgICAgICBmeCA9IHRvRmxvYXQoZngpO1xuICAgICAgICAgICAgICAgIGZ5ID0gdG9GbG9hdChmeSk7XG4gICAgICAgICAgICAgICAgcG93KGZ4IC0gLjUsIDIpICsgcG93KGZ5IC0gLjUsIDIpID4gLjI1ICYmIChmeSA9IG1hdGguc3FydCguMjUgLSBwb3coZnggLSAuNSwgMikpICogKChmeSA+IC41KSAqIDIgLSAxKSArIC41KTtcbiAgICAgICAgICAgICAgICBmeGZ5ID0gZnggKyBTICsgZnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gRTtcbiAgICAgICAgfSk7XG4gICAgICAgIGdyYWRpZW50ID0gZ3JhZGllbnQuc3BsaXQoL1xccypcXC1cXHMqLyk7XG4gICAgICAgIGlmICh0eXBlID09IFwibGluZWFyXCIpIHtcbiAgICAgICAgICAgIHZhciBhbmdsZSA9IGdyYWRpZW50LnNoaWZ0KCk7XG4gICAgICAgICAgICBhbmdsZSA9IC10b0Zsb2F0KGFuZ2xlKTtcbiAgICAgICAgICAgIGlmIChpc05hTihhbmdsZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgI
57612H1cbiAgICAgICAgfVxuICAgICAgICB2YXIgZG90cyA9IFIuX3BhcnNlRG90cyhncmFkaWVudCk7XG4gICAgICAgIGlmICghZG90cykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgbyA9IG8uc2hhcGUgfHwgby5ub2RlO1xuICAgICAgICBpZiAoZG90cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIG8ucmVtb3ZlQ2hpbGQoZmlsbCk7XG4gICAgICAgICAgICBmaWxsLm9uID0gdHJ1ZTtcbiAgICAgICAgICAgIGZpbGwubWV0aG9kID0gXCJub25lXCI7XG4gICAgICAgICAgICBmaWxsLmNvbG9yID0gZG90c1swXS5jb2xvcjtcbiAgICAgICAgICAgIGZpbGwuY29sb3IyID0gZG90c1tkb3RzLmxlbmd0aCAtIDFdLmNvbG9yO1xuICAgICAgICAgICAgdmFyIGNscnMgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGRvdHMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGRvdHNbaV0ub2Zmc2V0ICYmIGNscnMucHVzaChkb3RzW2ldLm9mZnNldCArIFMgKyBkb3RzW2ldLmNvbG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGwuY29sb3JzID0gY2xycy5sZW5ndGggPyBjbHJzLmpvaW4oKSA6IFwiMCUgXCIgKyBmaWxsLmNvbG9yO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT0gXCJyYWRpYWxcIikge1xuICAgICAgICAgICAgICAgIGZpbGwudHlwZSA9IFwiZ3JhZGllbnRUaXRsZVwiO1xuICAgICAgICAgICAgICAgIGZpbGwuZm9jdXMgPSBcIjEwMCVcIjtcbiAgICAgICAgICAgICAgICBmaWxsLmZvY3Vzc2l6ZSA9IFwiMCAwXCI7XG4gICAgICAgICAgICAgICAgZmlsbC5mb2N1c3Bvc2l0aW9uID0gZnhmeTtcbiAgICAgICAgICAgICAgICBmaWxsLmFuZ2xlID0gMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZmlsbC5yb3RhdGU9IHRydWU7XG4gICAgICAgICAgICAgICAgZmlsbC50eXBlID0gXCJncmFkaWVudFwiO1xuICAgICAgICAgICAgICAgIGZpbGwuYW5nbGUgPSAoMjcwIC0gYW5nbGUpICUgMzYwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgby5hcHBlbmRDaGlsZChmaWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMTtcbiAgICB9LFxuICAgIEVsZW1lbnQgPSBmdW5jdGlvbiAobm9kZSwgdm1sKSB7XG4gICAgICAgIHRoaXNbMF0gPSB0aGlzLm5vZGUgPSBub2RlO1xuICAgICAgICBub2RlLnJhcGhhZWwgPSB0cnVlO1xuICAgICAgICB0aGlzLmlkID0gUi5fb2lkKys7XG4gICAgICAgIG5vZGUucmFwaGFlbGlkID0gdGhpcy5pZDtcbiAgICAgICAgdGhpcy5YID0gMDtcbiAgICAgICAgdGhpcy5ZID0gMDtcbiAgICAgICAgdGhpcy5hdHRycyA9IHt9O1xuICAgICAgICB0aGlzLnBhcGVyID0gdm1sO1xuICAgICAgICB0aGlzLm1hdHJpeCA9IFIubWF0cml4KCk7XG4gICAgICAgIHRoaXMuXyA9IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogW10sXG4gICAgICAgICAgICBzeDogMSxcbiAgICAgICAgICAgIHN5OiAxLFxuICAgICAgICAgICAgZHg6IDAsXG4gICAgICAgICAgICBkeTogMCxcbiAgICAgICAgICAgIGRlZzogMCxcbiAgICAgICAgICAgIGRpcnR5OiAxLFxuICAgICAgICAgICAgZGlydHlUOiAxXG4gICAgICAgIH07XG4gICAgICAgICF2bWwuYm90dG9tICYmICh2bWwuYm90dG9tID0gdGhpcyk7XG4gICAgICAgIHRoaXMucHJldiA9IHZtbC50b3A7XG4gICAgICAgIHZtbC50b3AgJiYgKHZtbC50b3AubmV4dCA9IHRoaXMpO1xuICAgICAgICB2bWwudG9wID0gdGhpcztcbiAgICAgICAgdGhpcy5uZXh0ID0gbnVsbDtcbiAgICB9O1xuICAgIHZhciBlbHByb3RvID0gUi5lbDtcblxuICAgIEVsZW1lbnQucHJvdG90eXBlID0gZWxwcm90bztcbiAgICBlbHByb3RvLmNvbnN0cnVjdG9yID0gRWxlbWVudDtcbiAgICBlbHByb3RvLnRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0c3RyKSB7XG4gICAgICAgIGlmICh0c3RyID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl8udHJhbnNmb3JtO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2YnMgPSB0aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQsXG4gICAgICAgICAgICB2YnQgPSB2YnMgPyBcInNcIiArIFt2YnMuc2NhbGUsIHZicy5zY2FsZV0gKyBcIi0xLTF0XCIgKyBbdmJzLmR4LCB2YnMuZHldIDogRSxcbiAgICAgICAgICAgIG9sZHQ7XG4gICAgICAgIGlmICh2YnMpIHtcbiAgICAgICAgICAgIG9sZHQgPSB0c3RyID0gU3RyKHRzdHIpLnJlcGxhY2UoL1xcLnszfXxcXHUyMDI2L2csIHRoaXMuXy50cmFuc2Zvcm0gfHwgRSk7XG4gICAgICAgIH1cbiAgICAgICAgUi5fZXh0cmFjdFRyYW5zZm9ybSh0aGlzLCB2YnQgKyB0c3RyKTtcbiAgICAgICAgdmFyIG1hdHJpeCA9IHRoaXMubWF0cml4LmNsb25lKCksXG4gICAgICAgICAgICBza2V3ID0gdGhpcy5za2V3LFxuICAgICAgICAgICAgbyA9IHRoaXMubm9kZSxcbiAgICAgICAgICAgIHNwbGl0LFxuICAgICAgICAgICAgaXNHcmFkID0gflN0cih0aGlzLmF0dHJzLmZpbGwpLmluZGV4T2YoXCItXCIpLFxuICAgICAgICAgICAgaXNQYXR0ID0gIVN0cih0aGlzLmF0dHJzLmZpbGwpLmluZGV4T2YoXCJ1cmwoXCIpO1xuICAgICAgICBtYXRyaXgudHJhbnNsYXRlKDEsIDEpO1xuICAgICAgICBpZiAoaXNQYXR0IHx8IGlzR3JhZCB8fCB0aGlzLnR5cGUgPT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgICBza2V3Lm1hdHJpeCA9IFwiMSAwIDAgMVwiO1xuICAgICAgICAgICAgc2tldy5vZmZzZXQgPSBcIjAgMFwiO1xuICAgICAgICAgICAgc3BsaXQgPSBtYXRyaXguc3BsaXQoKTtcbiAgICAgICAgICAgIGlmICgoaXNHcmFkICYmIHNwbGl0Lm5vUm90YXRpb24pIHx8ICFzcGxpdC5pc1NpbXBsZSkge1xuICAgICAgICAgICAgICAgIG8uc3R5bGUuZmlsdGVyID0gbWF0cml4LnRvRmlsdGVyKCk7XG4gICAgICAgICAgICAgICAgdmFyIGJiID0gdGhpcy5nZXRCQm94KCksXG4gICAgICAgICAgICAgICAgICAgIGJidCA9IHRoaXMuZ2V0QkJveCgxKSxcbiAgICAgICAgICAgICAgICAgICAgZHggPSBiYi54IC0gYmJ0LngsXG4gICAgICAgICAgICAgICAgICAgIGR5ID0gYmIueSAtIGJidC55O1xuICAgICAgICAgICAgICAgIG8uY29vcmRvcmlnaW4gPSAoZHggKiAtem9vbSkgKyBTICsgKGR5ICogLXpvb20pO1xuICAgICAgICAgICAgICAgI
57612HNldENvb3Jkcyh0aGlzLCAxLCAxLCBkeCwgZHksIDApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvLnN0eWxlLmZpbHRlciA9IEU7XG4gICAgICAgICAgICAgICAgc2V0Q29vcmRzKHRoaXMsIHNwbGl0LnNjYWxleCwgc3BsaXQuc2NhbGV5LCBzcGxpdC5keCwgc3BsaXQuZHksIHNwbGl0LnJvdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvLnN0eWxlLmZpbHRlciA9IEU7XG4gICAgICAgICAgICBza2V3Lm1hdHJpeCA9IFN0cihtYXRyaXgpO1xuICAgICAgICAgICAgc2tldy5vZmZzZXQgPSBtYXRyaXgub2Zmc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZHQgIT09IG51bGwpIHsgLy8gZW1wdHkgc3RyaW5nIHZhbHVlIGlzIHRydWUgYXMgd2VsbFxuICAgICAgICAgICAgdGhpcy5fLnRyYW5zZm9ybSA9IG9sZHQ7XG4gICAgICAgICAgICBSLl9leHRyYWN0VHJhbnNmb3JtKHRoaXMsIG9sZHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZWxwcm90by5yb3RhdGUgPSBmdW5jdGlvbiAoZGVnLCBjeCwgY3kpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlZyA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZGVnID0gU3RyKGRlZykuc3BsaXQoc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKGRlZy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBjeCA9IHRvRmxvYXQoZGVnWzFdKTtcbiAgICAgICAgICAgIGN5ID0gdG9GbG9hdChkZWdbMl0pO1xuICAgICAgICB9XG4gICAgICAgIGRlZyA9IHRvRmxvYXQoZGVnWzBdKTtcbiAgICAgICAgKGN5ID09IG51bGwpICYmIChjeCA9IGN5KTtcbiAgICAgICAgaWYgKGN4ID09IG51bGwgfHwgY3kgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJCb3goMSk7XG4gICAgICAgICAgICBjeCA9IGJib3gueCArIGJib3gud2lkdGggLyAyO1xuICAgICAgICAgICAgY3kgPSBiYm94LnkgKyBiYm94LmhlaWdodCAvIDI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fLmRpcnR5VCA9IDE7XG4gICAgICAgIHRoaXMudHJhbnNmb3JtKHRoaXMuXy50cmFuc2Zvcm0uY29uY2F0KFtbXCJyXCIsIGRlZywgY3gsIGN5XV0pKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIChkeCwgZHkpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZHggPSBTdHIoZHgpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChkeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBkeSA9IHRvRmxvYXQoZHhbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGR4ID0gdG9GbG9hdChkeFswXSkgfHwgMDtcbiAgICAgICAgZHkgPSArZHkgfHwgMDtcbiAgICAgICAgaWYgKHRoaXMuXy5iYm94KSB7XG4gICAgICAgICAgICB0aGlzLl8uYmJveC54ICs9IGR4O1xuICAgICAgICAgICAgdGhpcy5fLmJib3gueSArPSBkeTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRyYW5zZm9ybSh0aGlzLl8udHJhbnNmb3JtLmNvbmNhdChbW1widFwiLCBkeCwgZHldXSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIGVscHJvdG8uc2NhbGUgPSBmdW5jdGlvbiAoc3gsIHN5LCBjeCwgY3kpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgc3ggPSBTdHIoc3gpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIGlmIChzeC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBzeSA9IHRvRmxvYXQoc3hbMV0pO1xuICAgICAgICAgICAgY3ggPSB0b0Zsb2F0KHN4WzJdKTtcbiAgICAgICAgICAgIGN5ID0gdG9GbG9hdChzeFszXSk7XG4gICAgICAgICAgICBpc05hTihjeCkgJiYgKGN4ID0gbnVsbCk7XG4gICAgICAgICAgICBpc05hTihjeSkgJiYgKGN5ID0gbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgc3ggPSB0b0Zsb2F0KHN4WzBdKTtcbiAgICAgICAgKHN5ID09IG51bGwpICYmIChzeSA9IHN4KTtcbiAgICAgICAgKGN5ID09IG51bGwpICYmIChjeCA9IGN5KTtcbiAgICAgICAgaWYgKGN4ID09IG51bGwgfHwgY3kgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJCb3goMSk7XG4gICAgICAgIH1cbiAgICAgICAgY3ggPSBjeCA9PSBudWxsID8gYmJveC54ICsgYmJveC53aWR0aCAvIDIgOiBjeDtcbiAgICAgICAgY3kgPSBjeSA9PSBudWxsID8gYmJveC55ICsgYmJveC5oZWlnaHQgLyAyIDogY3k7XG5cbiAgICAgICAgdGhpcy50cmFuc2Zvcm0odGhpcy5fLnRyYW5zZm9ybS5jb25jYXQoW1tcInNcIiwgc3gsIHN5LCBjeCwgY3ldXSkpO1xuICAgICAgICB0aGlzLl8uZGlydHlUID0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICF0aGlzLnJlbW92ZWQgJiYgKHRoaXMubm9kZS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIGVscHJvdG8uc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgIXRoaXMucmVtb3ZlZCAmJiAodGhpcy5ub2RlLnN0eWxlLmRpc3BsYXkgPSBFKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICAvLyBOZWVkZWQgdG8gZml4IHRoZSB2bWwgc2V0Vmlld0JveCBpc3N1ZXNcbiAgICBlbHByb3RvLmF1eEdldEJCb3ggPSBSLmVsLmdldEJCb3g7XG4gICAgZWxwcm90by5nZXRCQm94ID0gZnVuY3Rpb24oKXtcbiAgICAgIHZhciBiID0gdGhpcy5hdXhHZXRCQm94KCk7XG4gICAgICBpZiAodGhpcy5wYXBlciAmJiB0aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQpXG4gICAgICB7XG4gICAgICAgIHZhciBjID0ge307XG4gICAgICAgIHZhciB6ID0gMS90aGlzLnBhcGVyLl92aWV3Qm94U2hpZnQuc2NhbGU7XG4gICAgICAgIGMueCA9IGIueCAtIHRoaXMucGFwZXIuX3ZpZXdCb3hTaGlmdC5keDtcbiAgICAgICAgYy54ICo9IHo7XG4gICAgICAgIGMueSA9IGIueSAtIHRoaXMucGFwZXIuX3ZpZXdCb3hTaGlmdC5keTtcbiAgICAgICAgYy55ICo9IHo7XG4gICAgICAgIGMud2lkdGggID0gYi53aWR0aCAgKiB6O1xuICAgICAgICBjLmhlaWdodCA9IGIuaGVpZ2h0ICogejtcbiAgICAgICAgYy54MiA9IGMueCArIGMud2lkdGg7XG4gICAgICAgIGMueTIgPSBjLnkgKyBjLmhlaWdodDtcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9XG4gICAgICByZXR1cm4gYjtcbiAgICB9O1xuICAgIGVscHJvdG8uX2dldEJCb3ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgI
57612HJldHVybiB7fTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogdGhpcy5YICsgKHRoaXMuYmJ4IHx8IDApIC0gdGhpcy5XIC8gMixcbiAgICAgICAgICAgIHk6IHRoaXMuWSAtIHRoaXMuSCxcbiAgICAgICAgICAgIHdpZHRoOiB0aGlzLlcsXG4gICAgICAgICAgICBoZWlnaHQ6IHRoaXMuSFxuICAgICAgICB9O1xuICAgIH07XG4gICAgZWxwcm90by5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQgfHwgIXRoaXMubm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXBlci5fX3NldF9fICYmIHRoaXMucGFwZXIuX19zZXRfXy5leGNsdWRlKHRoaXMpO1xuICAgICAgICBSLmV2ZS51bmJpbmQoXCJyYXBoYWVsLiouKi5cIiArIHRoaXMuaWQpO1xuICAgICAgICBSLl90ZWFyKHRoaXMsIHRoaXMucGFwZXIpO1xuICAgICAgICB0aGlzLm5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLm5vZGUpO1xuICAgICAgICB0aGlzLnNoYXBlICYmIHRoaXMuc2hhcGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLnNoYXBlKTtcbiAgICAgICAgZm9yICh2YXIgaSBpbiB0aGlzKSB7XG4gICAgICAgICAgICB0aGlzW2ldID0gdHlwZW9mIHRoaXNbaV0gPT0gXCJmdW5jdGlvblwiID8gUi5fcmVtb3ZlZEZhY3RvcnkoaSkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlZCA9IHRydWU7XG4gICAgfTtcbiAgICBlbHByb3RvLmF0dHIgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgYSBpbiB0aGlzLmF0dHJzKSBpZiAodGhpcy5hdHRyc1toYXNdKGEpKSB7XG4gICAgICAgICAgICAgICAgcmVzW2FdID0gdGhpcy5hdHRyc1thXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlcy5ncmFkaWVudCAmJiByZXMuZmlsbCA9PSBcIm5vbmVcIiAmJiAocmVzLmZpbGwgPSByZXMuZ3JhZGllbnQpICYmIGRlbGV0ZSByZXMuZ3JhZGllbnQ7XG4gICAgICAgICAgICByZXMudHJhbnNmb3JtID0gdGhpcy5fLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcInN0cmluZ1wiKSkge1xuICAgICAgICAgICAgaWYgKG5hbWUgPT0gZmlsbFN0cmluZyAmJiB0aGlzLmF0dHJzLmZpbGwgPT0gXCJub25lXCIgJiYgdGhpcy5hdHRycy5ncmFkaWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF0dHJzLmdyYWRpZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5hbWVzID0gbmFtZS5zcGxpdChzZXBhcmF0b3IpLFxuICAgICAgICAgICAgICAgIG91dCA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBuYW1lc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAobmFtZSBpbiB0aGlzLmF0dHJzKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtuYW1lXSA9IHRoaXMuYXR0cnNbbmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChSLmlzKHRoaXMucGFwZXIuY3VzdG9tQXR0cmlidXRlc1tuYW1lXSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgICAgICBvdXRbbmFtZV0gPSB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbbmFtZV0uZGVmO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtuYW1lXSA9IFIuX2F2YWlsYWJsZUF0dHJzW25hbWVdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpaSAtIDEgPyBvdXQgOiBvdXRbbmFtZXNbMF1dO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmF0dHJzICYmIHZhbHVlID09IG51bGwgJiYgUi5pcyhuYW1lLCBcImFycmF5XCIpKSB7XG4gICAgICAgICAgICBvdXQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGlpID0gbmFtZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3V0W25hbWVbaV1dID0gdGhpcy5hdHRyKG5hbWVbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfVxuICAgICAgICB2Y
57612XIgcGFyYW1zO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFyYW1zID0ge307XG4gICAgICAgICAgICBwYXJhbXNbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZSA9PSBudWxsICYmIFIuaXMobmFtZSwgXCJvYmplY3RcIikgJiYgKHBhcmFtcyA9IG5hbWUpO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBldmUoXCJyYXBoYWVsLmF0dHIuXCIgKyBrZXkgKyBcIi5cIiArIHRoaXMuaWQsIHRoaXMsIHBhcmFtc1trZXldKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zKSB7XG4gICAgICAgICAgICBmb3IgKGtleSBpbiB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXMpIGlmICh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNbaGFzXShrZXkpICYmIHBhcmFtc1toYXNdKGtleSkgJiYgUi5pcyh0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XSwgXCJmdW5jdGlvblwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXIgPSB0aGlzLnBhcGVyLmN1c3RvbUF0dHJpYnV0ZXNba2V5XS5hcHBseSh0aGlzLCBbXS5jb25jYXQocGFyYW1zW2tleV0pKTtcbiAgICAgICAgICAgICAgICB0aGlzLmF0dHJzW2tleV0gPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBzdWJrZXkgaW4gcGFyKSBpZiAocGFyW2hhc10oc3Via2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXNbc3Via2V5XSA9IHBhcltzdWJrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoaXMucGFwZXIuY2FudmFzLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIGlmIChwYXJhbXMudGV4dCAmJiB0aGlzLnR5cGUgPT0gXCJ0ZXh0XCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHRwYXRoLnN0cmluZyA9IHBhcmFtcy50ZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2V0RmlsbEFuZFN0cm9rZSh0aGlzLCBwYXJhbXMpO1xuICAgICAgICAgICAgLy8gdGhpcy5wYXBlci
576125jYW52YXMuc3R5bGUuZGlzcGxheSA9IEU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLnRvRnJvbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICF0aGlzLnJlbW92ZWQgJiYgdGhpcy5ub2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQodGhpcy5ub2RlKTtcbiAgICAgICAgdGhpcy5wYXBlciAmJiB0aGlzLnBhcGVyLnRvcCAhPSB0aGlzICYmIFIuX3RvZnJvbnQodGhpcywgdGhpcy5wYXBlcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZWxwcm90by50b0JhY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm5vZGUucGFyZW50Tm9kZS5maXJzdENoaWxkICE9IHRoaXMubm9kZSkge1xuICAgICAgICAgICAgdGhpcy5ub2RlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMubm9kZSwgdGhpcy5ub2RlLnBhcmVudE5vZGUuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICBSLl90b2JhY2sodGhpcywgdGhpcy5wYXBlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmluc2VydEFmdGVyID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKHRoaXMucmVtb3ZlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsZW1lbnQuY29uc3RydWN0b3IgPT0gUi5zdC5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgZWxlbWVudCA9IGVsZW1lbnRbZWxlbWVudC5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWxlbWVudC5ub2RlLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICBlbGVtZW50Lm5vZGUucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5ub2RlLCBlbGVtZW50Lm5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5ub2RlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQodGhpcy5ub2RlKTtcbiAgICAgICAgfVxuICAgICAgICBSLl9pbnNlcnRhZnRlcih0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmluc2VydEJlZm9yZSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGlmICh0aGlzLnJlbW92ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlbGVtZW50LmNvbnN0cnVjdG9yID09IFIuc3QuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGVsZW1lbnQgPSBlbGVtZW50WzBdO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQubm9kZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLm5vZGUsIGVsZW1lbnQubm9kZSk7XG4gICAgICAgIFIuX2luc2VydGJlZm9yZSh0aGlzLCBlbGVtZW50LCB0aGlzLnBhcGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBlbHByb3RvLmJsdXIgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICB2Y
57612XIgcyA9IHRoaXMubm9kZS5ydW50aW1lU3R5bGUsXG4gICAgICAgICAgICBmID0gcy5maWx0ZXI7XG4gICAgICAgIGYgPSBmLnJlcGxhY2UoYmx1cnJlZ2V4cCwgRSk7XG4gICAgICAgIGlmICgrc2l6ZSAhPT0gMCkge1xuICAgICAgICAgICAgdGhpcy5hdHRycy5ibHVyID0gc2l6ZTtcbiAgICAgICAgICAgIHMuZmlsdGVyID0gZiArIFMgKyBtcyArIFwiLkJsdXIocGl4ZWxyYWRpdXM9XCIgKyAoK3NpemUgfHwgMS41KSArIFwiKVwiO1xuICAgICAgICAgICAgcy5tYXJnaW4gPSBSLmZvcm1hdChcIi17MH1weCAwIDAgLXswfXB4XCIsIHJvdW5kKCtzaXplIHx8IDEuNSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcy5maWx0ZXIgPSBmO1xuICAgICAgICAgICAgcy5tYXJnaW4gPSAwO1xuICAgICAgICAgICAgZGVsZXRlIHRoaXMuYXR0cnMuYmx1cjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgUi5fZW5naW5lLnBhdGggPSBmdW5jdGlvbiAocGF0aFN0cmluZywgdm1sKSB7XG4gICAgICAgIHZhciBlbCA9IGNyZWF0ZU5vZGUoXCJzaGFwZVwiKTtcbiAgICAgICAgZWwuc3R5bGUuY3NzVGV4dCA9IGNzc0RvdDtcbiAgICAgICAgZWwuY29vcmRzaXplID0gem9vbSArIFMgKyB6b29tO1xuICAgICAgICBlbC5jb29yZG9yaWdpbiA9IHZtbC5jb29yZG9yaWdpbjtcbiAgICAgICAgdmFyIHAgPSBuZXcgRWxlbWVudChlbCwgdm1sKSxcbiAgICAgICAgICAgIGF0dHIgPSB7ZmlsbDogXCJub25lXCIsIHN0cm9rZTogXCIjMDAwXCJ9O1xuICAgICAgICBwYXRoU3RyaW5nICYmIChhdHRyLnBhdGggPSBwYXRoU3RyaW5nKTtcbiAgICAgICAgcC50eXBlID0gXCJwYXRoXCI7XG4gICAgICAgIHAucGF0aCA9IFtdO1xuICAgICAgICBwLlBhdGggPSBFO1xuICAgICAgICBzZXRGaWxsQW5kU3Ryb2tlKHAsIGF0dHIpO1xuICAgICAgICB2bWwuY2FudmFzICYmIHZtbC5jYW52YXMuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICB2Y
57612XIgc2tldyA9IGNyZWF0ZU5vZGUoXCJza2V3XCIpO1xuICAgICAgICBza2V3Lm9uID0gdHJ1ZTtcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQoc2tldyk7XG4gICAgICAgIHAuc2tldyA9IHNrZXc7XG4gICAgICAgIHAudHJhbnNmb3JtKEUpO1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5yZWN0ID0gZnVuY3Rpb24gKHZtbCwgeCwgeSwgdywgaCwgcikge1xuICAgICAgICB2YXIgcGF0aCA9IFIuX3JlY3RQYXRoKHgsIHksIHcsIGgsIHIpLFxuICAgICAgICAgICAgcmVzID0gdm1sLnBhdGgocGF0aCksXG4gICAgICAgICAgICBhID0gcmVzLmF0dHJzO1xuICAgICAgICByZXMuWCA9IGEueCA9IHg7XG4gICAgICAgIHJlcy5ZID0gYS55ID0geTtcbiAgICAgICAgcmVzLlcgPSBhLndpZHRoID0gdztcbiAgICAgICAgcmVzLkggPSBhLmhlaWdodCA9IGg7XG4gICAgICAgIGEuciA9IHI7XG4gICAgICAgIGEucGF0aCA9IHBhdGg7XG4gICAgICAgIHJlcy50eXBlID0gXCJyZWN0XCI7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuZWxsaXBzZSA9IGZ1bmN0aW9uICh2bWwsIHgsIHksIHJ4LCByeSkge1xuICAgICAgICB2YXIgcmVzID0gdm1sLnBhdGgoKSxcbiAgICAgICAgICAgIGEgPSByZXMuYXR0cnM7XG4gICAgICAgIHJlcy5YID0geCAtIHJ4O1xuICAgICAgICByZXMuWSA9IHkgLSByeTtcbiAgICAgICAgcmVzLlcgPSByeCAqIDI7XG4gICAgICAgIHJlcy5IID0gcnkgKiAyO1xuICAgICAgICByZXMudHlwZSA9IFwiZWxsaXBzZVwiO1xuICAgICAgICBzZXRGaWxsQW5kU3Ryb2tlKHJlcywge1xuICAgICAgICAgICAgY3g6IHgsXG4gICAgICAgICAgICBjeTogeSxcbiAgICAgICAgICAgIHJ4OiByeCxcbiAgICAgICAgICAgIHJ5OiByeVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5jaXJjbGUgPSBmdW5jdGlvbiAodm1sLCB4LCB5LCByKSB7XG4gICAgICAgIHZhciByZXMgPSB2bWwucGF0aCgpLFxuICAgICAgICAgICAgYSA9IHJlcy5hdHRycztcbiAgICAgICAgcmVzLlggPSB4IC0gcjtcbiAgICAgICAgcmVzLlkgPSB5IC0gcjtcbiAgICAgICAgcmVzLlcgPSByZXMuSCA9IHIgKiAyO1xuICAgICAgICByZXMudHlwZSA9IFwiY2lyY2xlXCI7XG4gICAgICAgIHNldEZpbGxBbmRTdHJva2UocmVzLCB7XG4gICAgICAgICAgICBjeDogeCxcbiAgICAgICAgICAgIGN5OiB5LFxuICAgICAgICAgICAgcjogclxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS5pbWFnZSA9IGZ1bmN0aW9uICh2bWwsIHNyYywgeCwgeSwgdywgaCkge1xuICAgICAgICB2Y
57612XIgcGF0aCA9IFIuX3JlY3RQYXRoKHgsIHksIHcsIGgpLFxuICAgICAgICAgICAgcmVzID0gdm1sLnBhdGgocGF0aCkuYXR0cih7c3Ryb2tlOiBcIm5vbmVcIn0pLFxuICAgICAgICAgICAgYSA9IHJlcy5hdHRycyxcbiAgICAgICAgICAgIG5vZGUgPSByZXMubm9kZSxcbiAgICAgICAgICAgIGZpbGwgPSBub2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKGZpbGxTdHJpbmcpWzBdO1xuICAgICAgICBhLnNyYyA9IHNyYztcbiAgICAgICAgcmVzLlggPSBhLnggPSB4O1xuICAgICAgICByZXMuWSA9IGEueSA9IHk7XG4gICAgICAgIHJlcy5XID0gYS53aWR0aCA9IHc7XG4gICAgICAgIHJlcy5IID0gYS5oZWlnaHQgPSBoO1xuICAgICAgICBhLnBhdGggPSBwYXRoO1xuICAgICAgICByZXMudHlwZSA9IFwiaW1hZ2VcIjtcbiAgICAgICAgZmlsbC5wYXJlbnROb2RlID09IG5vZGUgJiYgbm9kZS5yZW1vdmVDaGlsZChmaWxsKTtcbiAgICAgICAgZmlsbC5yb3RhdGUgPSB0cnVlO1xuICAgICAgICBmaWxsLnNyYyA9IHNyYztcbiAgICAgICAgZmlsbC50eXBlID0gXCJ0aWxlXCI7XG4gICAgICAgIHJlcy5fLmZpbGxwb3MgPSBbeCwgeV07XG4gICAgICAgIHJlcy5fLmZpbGxzaXplID0gW3csIGhdO1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKGZpbGwpO1xuICAgICAgICBzZXRDb29yZHMocmVzLCAxLCAxLCAwLCAwLCAwKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFIuX2VuZ2luZS50ZXh0ID0gZnVuY3Rpb24gKHZtbCwgeCwgeSwgdGV4dCkge1xuICAgICAgICB2Y
57612XIgZWwgPSBjcmVhdGVOb2RlKFwic2hhcGVcIiksXG4gICAgICAgICAgICBwYXRoID0gY3JlYXRlTm9kZShcInBhdGhcIiksXG4gICAgICAgICAgICBvID0gY3JlYXRlTm9kZShcInRleHRwYXRoXCIpO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB0ZXh0ID0gdGV4dCB8fCBcIlwiO1xuICAgICAgICBwYXRoLnYgPSBSLmZvcm1hdChcIm17MH0sezF9bHsyfSx7MX1cIiwgcm91bmQoeCAqIHpvb20pLCByb3VuZCh5ICogem9vbSksIHJvdW5kKHggKiB6b29tKSArIDEpO1xuICAgICAgICBwYXRoLnRleHRwYXRob2sgPSB0cnVlO1xuICAgICAgICBvLnN0cmluZyA9IFN0cih0ZXh0KTtcbiAgICAgICAgby5vbiA9IHRydWU7XG4gICAgICAgIGVsLnN0eWxlLmNzc1RleHQgPSBjc3NEb3Q7XG4gICAgICAgIGVsLmNvb3Jkc2l6ZSA9IHpvb20gKyBTICsgem9vbTtcbiAgICAgICAgZWwuY29vcmRvcmlnaW4gPSBcIjAgMFwiO1xuICAgICAgICB2YXIgcCA9IG5ldyBFbGVtZW50KGVsLCB2bWwpLFxuICAgICAgICAgICAgYXR0ciA9IHtcbiAgICAgICAgICAgICAgICBmaWxsOiBcIiMwMDBcIixcbiAgICAgICAgICAgICAgICBzdHJva2U6IFwibm9uZVwiLFxuICAgICAgICAgICAgICAgIGZvbnQ6IFIuX2F2YWlsYWJsZUF0dHJzLmZvbnQsXG4gICAgICAgICAgICAgICAgdGV4dDogdGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgcC5zaGFwZSA9IGVsO1xuICAgICAgICBwLnBhdGggPSBwYXRoO1xuICAgICAgICBwLnRleHRwYXRoID0gbztcbiAgICAgICAgcC50eXBlID0gXCJ0ZXh0XCI7XG4gICAgICAgIHAuYXR0cnMudGV4dCA9IFN0cih0ZXh0KTtcbiAgICAgICAgcC5hdHRycy54ID0geDtcbiAgICAgICAgcC5hdHRycy55ID0geTtcbiAgICAgICAgcC5hdHRycy53ID0gMTtcbiAgICAgICAgcC5hdHRycy5oID0gMTtcbiAgICAgICAgc2V0RmlsbEFuZFN0cm9rZShwLCBhdHRyKTtcbiAgICAgICAgZWwuYXBwZW5kQ2hpbGQobyk7XG4gICAgICAgIGVsLmFwcGVuZENoaWxkKHBhdGgpO1xuICAgICAgICB2bWwuY2FudmFzLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgdmFyIHNrZXcgPSBjcmVhdGVOb2RlKFwic2tld1wiKTtcbiAgICAgICAgc2tldy5vbiA9IHRydWU7XG4gICAgICAgIGVsLmFwcGVuZENoaWxkKHNrZXcpO1xuICAgICAgICBwLnNrZXcgPSBza2V3O1xuICAgICAgICBwLnRyYW5zZm9ybShFKTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfTtcbiAgICBSLl9lbmdpbmUuc2V0U2l6ZSA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHZhciBjcyA9IHRoaXMuY2FudmFzLnN0eWxlO1xuICAgICAgICB0aGlzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICB3aWR0aCA9PSArd2lkdGggJiYgKHdpZHRoICs9IFwicHhcIik7XG4gICAgICAgIGhlaWdodCA9PSAraGVpZ2h0ICYmIChoZWlnaHQgKz0gXCJweFwiKTtcbiAgICAgICAgY3Mud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY3MuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICBjcy5jbGlwID0gXCJyZWN0KDAgXCIgKyB3aWR0aCArIFwiIFwiICsgaGVpZ2h0ICsgXCIgMClcIjtcbiAgICAgICAgaWYgKHRoaXMuX3ZpZXdCb3gpIHtcbiAgICAgICAgICAgIFIuX2VuZ2luZS5zZXRWaWV3Qm94LmFwcGx5KHRoaXMsIHRoaXMuX3ZpZXdCb3gpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgUi5fZW5naW5lLnNldFZpZXdCb3ggPSBmdW5jdGlvbiAoeCwgeSwgdywgaCwgZml0KSB7XG4gICAgICAgIFIuZXZlKFwicmFwaGFlbC5zZXRWaWV3Qm94XCIsIHRoaXMsIHRoaXMuX3ZpZXdCb3gsIFt4LCB5LCB3LCBoLCBmaXRdKTtcbiAgICAgICAgdmFyIHBhcGVyU2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxuICAgICAgICAgICAgd2lkdGggPSBwYXBlclNpemUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQgPSBwYXBlclNpemUuaGVpZ2h0LFxuICAgICAgICAgICAgSCwgVztcbiAgICAgICAgaWYgKGZpdCkge1xuICAgICAgICAgICAgSCA9IGhlaWdodCAvIGg7XG4gICAgICAgICAgICBXID0gd2lkdGggLyB3O1xuICAgICAgICAgICAgaWYgKHcgKiBIIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICB4IC09ICh3aWR0aCAtIHcgKiBIKSAvIDIgLyBIO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGggKiBXIDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgeSAtPSAoaGVpZ2h0IC0gaCAqIFcpIC8gMiAvIFc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmlld0JveCA9IFt4LCB5LCB3LCBoLCAhIWZpdF07XG4gICAgICAgIHRoaXMuX3ZpZXdCb3hTaGlmdCA9IHtcbiAgICAgICAgICAgIGR4OiAteCxcbiAgICAgICAgICAgIGR5OiAteSxcbiAgICAgICAgICAgIHNjYWxlOiBwYXBlclNpemVcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgZWwudHJhbnNmb3JtKFwiLi4uXCIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICB2YXIgY3JlYXRlTm9kZTtcbiAgICBSLl9lbmdpbmUuaW5pdFdpbiA9IGZ1bmN0aW9uICh3aW4pIHtcbiAgICAgICAgICAgIHZhciBkb2MgPSB3aW4uZG9jdW1lbnQ7XG4gICAgICAgICAgICBpZiAoZG9jLnN0eWxlU2hlZXRzLmxlbmd0aCA8IDMxKSB7XG4gICAgICAgICAgICAgICAgZG9jLmNyZWF0ZVN0eWxlU2hlZXQoKS5hZGRSdWxlKFwiLnJ2bWxcIiwgXCJiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKVwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gbW9yZSByb29tLCBhZGQgdG8gdGhlIGV4aXN0aW5nIG9uZVxuICAgICAgICAgICAgICAgIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzMTE5NCUyOFZTLjg1JTI5LmFzcHhcbiAgICAgICAgICAgICAgICBkb2Muc3R5bGVTaGVldHNbMF0uYWRkUnVsZShcIi5ydm1sXCIsIFwiYmVoYXZpb3I6dXJsKCNkZWZhdWx0I1ZNTClcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC
57612Fkb2MubmFtZXNwYWNlcy5ydm1sICYmIGRvYy5uYW1lc3BhY2VzLmFkZChcInJ2bWxcIiwgXCJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbFwiKTtcbiAgICAgICAgICAgICAgICBjcmVhdGVOb2RlID0gZnVuY3Rpb24gKHRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVFbGVtZW50KCc8cnZtbDonICsgdGFnTmFtZSArICcgY2xhc3M9XCJydm1sXCI+Jyk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjcmVhdGVOb2RlID0gZnVuY3Rpb24gKHRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVFbGVtZW50KCc8JyArIHRhZ05hbWUgKyAnIHhtbG5zPVwidXJuOnNjaGVtYXMtbWljcm9zb2Z0LmNvbTp2bWxcIiBjbGFzcz1cInJ2bWxcIj4nKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIFIuX2VuZ2luZS5pbml0V2luKFIuX2cud2luKTtcbiAgICBSLl9lbmdpbmUuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29uID0gUi5fZ2V0Q29udGFpbmVyLmFwcGx5KDAsIGFyZ3VtZW50cyksXG4gICAgICAgICAgICBjb250YWluZXIgPSBjb24uY29udGFpbmVyLFxuICAgICAgICAgICAgaGVpZ2h0ID0gY29uLmhlaWdodCxcbiAgICAgICAgICAgIHMsXG4gICAgICAgICAgICB3aWR0aCA9IGNvbi53aWR0aCxcbiAgICAgICAgICAgIHggPSBjb24ueCxcbiAgICAgICAgICAgIHkgPSBjb24ueTtcbiAgICAgICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlZNTCBjb250YWluZXIgbm90IGZvdW5kLlwiKTtcbiAgICAgICAgfVxuICAgICAgICB2Y
57612XIgcmVzID0gbmV3IFIuX1BhcGVyLFxuICAgICAgICAgICAgYyA9IHJlcy5jYW52YXMgPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwiZGl2XCIpLFxuICAgICAgICAgICAgY3MgPSBjLnN0eWxlO1xuICAgICAgICB4ID0geCB8fCAwO1xuICAgICAgICB5ID0geSB8fCAwO1xuICAgICAgICB3aWR0aCA9IHdpZHRoIHx8IDUxMjtcbiAgICAgICAgaGVpZ2h0ID0gaGVpZ2h0IHx8IDM0MjtcbiAgICAgICAgcmVzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIHJlcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHdpZHRoID09ICt3aWR0aCAmJiAod2lkdGggKz0gXCJweFwiKTtcbiAgICAgICAgaGVpZ2h0ID09ICtoZWlnaHQgJiYgKGhlaWdodCArPSBcInB4XCIpO1xuICAgICAgICByZXMuY29vcmRzaXplID0gem9vbSAqIDFlMyArIFMgKyB6b29tICogMWUzO1xuICAgICAgICByZXMuY29vcmRvcmlnaW4gPSBcIjAgMFwiO1xuICAgICAgICByZXMuc3BhbiA9IFIuX2cuZG9jLmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICByZXMuc3Bhbi5zdHlsZS5jc3NUZXh0ID0gXCJwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0Oi05OTk5ZW07dG9wOi05OTk5ZW07cGFkZGluZzowO21hcmdpbjowO2xpbmUtaGVpZ2h0OjE7XCI7XG4gICAgICAgIGMuYXBwZW5kQ2hpbGQocmVzLnNwYW4pO1xuICAgICAgICBjcy5jc3NUZXh0ID0gUi5mb3JtYXQoXCJ0b3A6MDtsZWZ0OjA7d2lkdGg6ezB9O2hlaWdodDp7MX07ZGlzcGxheTppbmxpbmUtYmxvY2s7cG9zaXRpb246cmVsYXRpdmU7Y2xpcDpyZWN0KDAgezB9IHsxfSAwKTtvdmVyZmxvdzpoaWRkZW5cIiwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGlmIChjb250YWluZXIgPT0gMSkge1xuICAgICAgICAgICAgUi5fZy5kb2MuYm9keS5hcHBlbmRDaGlsZChjKTtcbiAgICAgICAgICAgIGNzLmxlZnQgPSB4ICsgXCJweFwiO1xuICAgICAgICAgICAgY3MudG9wID0geSArIFwicHhcIjtcbiAgICAgICAgICAgIGNzLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNvbnRhaW5lci5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyLmluc2VydEJlZm9yZShjLCBjb250YWluZXIuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXMucmVuZGVyZml4ID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgUi5ldmUoXCJyYXBoYWVsLmNsZWFyXCIsIHRoaXMpO1xuICAgICAgICB0aGlzLmNhbnZhcy5pbm5lckhUTUwgPSBFO1xuICAgICAgICB0aGlzLnNwYW4gPSBSLl9nLmRvYy5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdGhpcy5zcGFuLnN0eWxlLmNzc1RleHQgPSBcInBvc2l0aW9uOmFic29sdXRlO2xlZnQ6LTk5OTllbTt0b3A6LTk5OTllbTtwYWRkaW5nOjA7bWFyZ2luOjA7bGluZS1oZWlnaHQ6MTtkaXNwbGF5OmlubGluZTtcIjtcbiAgICAgICAgdGhpcy5jYW52YXMuYXBwZW5kQ2hpbGQodGhpcy5zcGFuKTtcbiAgICAgICAgdGhpcy5ib3R0b20gPSB0aGlzLnRvcCA9IG51bGw7XG4gICAgfTtcbiAgICBSLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIFIuZXZlKFwicmFwaGFlbC5yZW1vdmVcIiwgdGhpcyk7XG4gICAgICAgIHRoaXMuY2FudmFzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5jYW52YXMpO1xuICAgICAgICBmb3IgKHZhciBpIGluIHRoaXMpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSB0eXBlb2YgdGhpc1tpXSA9PSBcImZ1bmN0aW9uXCIgPyBSLl9yZW1vdmVkRmFjdG9yeShpKSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIHZhciBzZXRwcm90byA9IFIuc3Q7XG4gICAgZm9yICh2YXIgbWV0aG9kIGluIGVscHJvdG8pIGlmIChlbHByb3RvW2hhc10obWV0aG9kKSAmJiAhc2V0cHJvdG9baGFzXShtZXRob2QpKSB7XG4gICAgICAgIHNldHByb3RvW21ldGhvZF0gPSAoZnVuY3Rpb24gKG1ldGhvZG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgICAgICAgICAgICBlbFttZXRob2RuYW1lXS5hcHBseShlbCwgYXJnKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pKG1ldGhvZCk7XG4gICAgfVxufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./dev/raphael.vml.js\n"); 57613 57614/***/ }), 57615
vendor: 40,047 bytes, lines 57616-57625
57616/***/ "./node_modules/eve-raphael/eve.js": 57617/*!*****************************************!*\ 57618 !*** ./node_modules/eve-raphael/eve.js ***! 57619 \*****************************************/ 57620/*! no static exports found */ 57621/***/ (function(module, exports, __webpack_require__) { 57622 57623eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n// \n// http://www.apache.org/licenses/LICENSE-2.0\n// \n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ \\\\\n// â Eve 0.5.0 - JavaScript Events Library â \\\\\n// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ⤠\\\\\n// â Author Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) â \\\\\n// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ \\\\\n\n(function (glob) {\n var version = \"0.5.0\",\n has = \"hasOwnProperty\",\n separator = /[\\.\\/]/,\n comaseparator = /\\s*,\\s*/,\n wildcard = \"*\",\n fun = function () {},\n numsort = function (a, b) {\n return a - b;\n },\n current_event,\n stop,\n events = {n: {}},\n firstDefined = function () {\n for (var i = 0, ii = this.length; i < ii; i++) {\n if (typeof this[i] != \"undefined\") {\n return this[i];\n }\n }\n },\n lastDefined = function () {\n var i = this.length;\n while (--i) {\n if (typeof this[i] != \"undefined\") {\n return this[i];\n }\n }\n },\n objtos = Object.prototype.toString,\n Str = String,\n isArray = Array.isArray || function (ar) {\n return ar instanceof Array || objtos.call(ar) == \"[object Array]\";\n };\n /*\\\n * eve\n [ method ]\n\n * Fires event with given `name`, given scope and other parameters.\n\n > Arguments\n\n - name (string) name of the *event*, dot (`.`) or slash (`/`) separated\n - scope (object) context for the event handlers\n - varargs (...) the rest of arguments will be sent to event handlers\n\n = (object) array of returned values from the listeners. Array has two methods `.firstDefined()` and `.lastDefined()` to get first or last not `undefined` value.\n \\*/\n var eve = function (name, scope) {\n var e = events,\n oldstop = stop,\n args = Array.prototype.slice.call(arguments, 2),\n listeners = eve.listeners(name),\n z = 0,\n f = false,\n l,\n indexed = [],\n queue = {},\n out = [],\n ce = current_event,\n errors = [];\n out.firstDefined = firstDefined;\n out.lastDefined = lastDefined;\n current_event = name;\n stop = 0;\n for (var i = 0, ii = listeners.length; i < ii; i++) if (\"zIndex\" in listeners[i]) {\n indexed.push(listeners[i].zIndex);\n if (listeners[i].zIndex < 0) {\n queue[listeners[i].zIndex] = listeners[i];\n }\n }\n indexed.sort(numsort);\n while (indexed[z] < 0) {\n l = queue[indexed[z++]];\n out.push(l.apply(scope, args));\n if (stop) {\n stop = oldstop;\n return out;\n }\n }\n for (i = 0; i < ii; i++) {\n l = listeners[i];\n if (\"zIndex\" in l) {\n if (l.zIndex == indexed[z]) {\n out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n do {\n z++;\n l = queue[indexed[z]];\n l && out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n } while (l)\n } else {\n queue[l.zIndex] = l;\n }\n } else {\n out.push(l.apply(scope, args));\n if (stop) {\n break;\n }\n }\n }\n stop = oldstop;\n current_event = ce;\n return out;\n };\n // Undocumented. Debug only.\n eve._events = events;\n /*\\\n * eve.listeners\n [ method ]\n\n * Internal method which gives you array of all event handlers that will be triggered by the given `name`.\n\n > Arguments\n\n - name (string) name of the event, dot (`.`) or slash (`/`) separated\n\n = (array) array of event handlers\n \\*/\n eve.listeners = function (name) {\n var names = isArray(name) ? name : name.split(separator),\n e = events,\n item,\n items,\n k,\n i,\n ii,\n j,\n jj,\n nes,\n es = [e],\n out = [];\n for (i = 0, ii = names.length; i < ii; i++) {\n nes = [];\n for (j = 0, jj = es.length; j < jj; j++) {\n e = es[j].n;\n items = [e[names[i]], e[wildcard]];\n k = 2;\n while (k--) {\n item = items[k];\n if (item) {\n nes.push(item);\n out = out.concat(item.f || []);\n }\n }\n }\n es = nes;\n }\n return out;\n };\n /*\\\n * eve.separator\n [ method ]\n\n * If for some reasons you donât like default separators (`.` or `/`) you can specify yours\n * here. Be aware that if you pass a string longer than one character it will be treated as\n * a list of characters.\n\n - separator (string) new separator. Empty string resets to default: `.` or `/`.\n \\*/\n eve.separator = function (sep) {\n if (sep) {\n sep = Str(sep).replace(/(?=[\\.\\^\\]\\[\\-])/g, \"\\\\\");\n sep = \"[\" + sep + \"]\";\n separator = new RegExp(sep);\n } else {\n separator = /[\\.\\/]/;\n }\n };\n /*\\\n * eve.on\n [ method ]\n **\n * Binds given event handler with a given name. You can use wildcards â`*`â for the names:\n | eve.on(\"*.under.*\", f);\n | eve(\"mouse.under.floor\"); // triggers f\n * Use @eve to trigger the listener.\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n **\n - name (array) if you donât want to use separators, you can use array of strings\n - f (function) event handler function\n **\n = (function) returned function accepts a single numeric parameter that represents z-index of the handler. It is an optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment. \n > Example:\n | eve.on(\"mouse\", eatIt)(2);\n | eve.on(\"mouse\", scream);\n | eve.on(\"mouse\", catchIt)(1);\n * This will ensure that `catchIt` function will be called before `eatIt`.\n *\n * If you want to put your handler before non-indexed handlers, specify a negative value.\n * Note: I assume most of the time you donât need to worry about z-index, but itâs nice to have this feature âjust in caseâ.\n \\*/\n eve.on = function (name, f) {\n if (typeof f != \"function\") {\n return function () {};\n }\n var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);\n for (var i = 0, ii = names.length; i < ii; i++) {\n (function (name) {\n var names = isArray(name) ? name : Str(name).split(separator),\n e = events,\n exist;\n for (var i = 0, ii = names.length; i < ii; i++) {\n e = e.n;\n e = e.hasOwnProperty(names[i]) && e[names[i]] || (e[names[i]] = {n: {}});\n }\n e.f = e.f || [];\n for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {\n exist = true;\n break;\n }\n !exist && e.f.push(f);\n }(names[i]));\n }\n return function (zIndex) {\n if (+zIndex == +zIndex) {\n f.zIndex = +zIndex;\n }\n };\n };\n /*\\\n * eve.f\n [ method ]\n **\n * Returns function that will fire given event with optional arguments.\n * Arguments that will be passed to the result function will be also\n * concated to the list of final arguments.\n | el.onclick = eve.f(\"click\", 1, 2);\n | eve.on(\"click\", function (a, b, c) {\n | console.log(a, b, c); // 1, 2, [event object]\n | });\n > Arguments\n - event (string) event name\n - varargs (â¦) and any other arguments\n = (function) possible event handler function\n \\*/\n eve.f = function (event) {\n var attrs = [].slice.call(arguments, 1);\n return function () {\n eve.apply(null, [event, null].concat(attrs).concat([].slice.call(arguments, 0)));\n };\n };\n /*\\\n * eve.stop\n [ method ]\n **\n * Is used inside an event handler to stop the event, preventing any subsequent listeners from firing.\n \\*/\n eve.stop = function () {\n stop = 1;\n };\n /*\\\n * eve.nt\n [ method ]\n **\n * Could be used inside event handler to figure out actual name of the event.\n **\n > Arguments\n **\n - subname (string) #optional subname of the event\n **\n = (string) name of the event, if `subname` is not specified\n * or\n = (boolean) `true`, if current eventâs name contains `subname`\n \\*/\n eve.nt = function (subname) {\n var cur = isArray(current_event) ? current_event.join(\".\") : current_event;\n if (subname) {\n return new RegExp(\"(?:\\\\.|\\\\/|^)\" + subname + \"(?:\\\\.|\\\\/|$)\").test(cur);\n }\n return cur;\n };\n /*\\\n * eve.nts\n [ method ]\n **\n * Could be used inside event handler to figure out actual name of the event.\n **\n **\n = (array) names of the event\n \\*/\n eve.nts = function () {\n return isArray(current_event) ? current_event : current_event.split(separator);\n };\n /*\\\n * eve.off\n [ method ]\n **\n * Removes given function from the list of event listeners assigned to given name.\n * If no arguments specified all the events will be cleared.\n **\n > Arguments\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n \\*/\n /*\\\n * eve.unbind\n [ method ]\n **\n * See @eve.off\n \\*/\n eve.off = eve.unbind = function (name, f) {\n if (!name) {\n eve._events = events = {n: {}};\n return;\n }\n var names = isArray(name) ? (isArray(name[0]) ? name : [name]) : Str(name).split(comaseparator);\n if (names.length > 1) {\n for (var i = 0, ii = names.length; i < ii; i++) {\n eve.off(names[i], f);\n }\n return;\n }\n names = isArray(name) ? name : Str(name).split(separator);\n var e,\n key,\n splice,\n i, ii, j, jj,\n cur = [events];\n for (i = 0, ii = names.length; i < ii; i++) {\n for (j = 0; j < cur.length; j += splice.length - 2) {\n splice = [j, 1];\n e = cur[j].n;\n if (names[i] != wildcard) {\n if (e[names[i]]) {\n splice.push(e[names[i]]);\n }\n } else {\n for (key in e) if (e[has](key)) {\n splice.push(e[key]);\n }\n }\n cur.splice.apply(cur, splice);\n }\n }\n for (i = 0, ii = cur.length; i < ii; i++) {\n e = cur[i];\n while (e.n) {\n if (f) {\n if (e.f) {\n for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) {\n e.f.splice(j, 1);\n break;\n }\n !e.f.length && delete e.f;\n }\n for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n var funcs = e.n[key].f;\n for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) {\n funcs.splice(j, 1);\n break;\n }\n !funcs.length && delete e.n[key].f;\n }\n } else {\n delete e.f;\n for (key in e.n) if (e.n[has](key) && e.n[key].f) {\n delete e.n[key].f;\n }\n }\n e = e.n;\n }\n }\n };\n /*\\\n * eve.once\n [ method ]\n **\n * Binds given event handler with a given name to only run once then unbind itself.\n | eve.once(\"login\", f);\n | eve(\"login\"); // triggers f\n | eve(\"login\"); // no listeners\n * Use @eve to trigger the listener.\n **\n > Arguments\n **\n - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards\n - f (function) event handler function\n **\n = (function) same return function as @eve.on\n \\*/\n eve.once = function (name, f) {\n var f2 = function () {\n eve.off(name, f2);\n return f.apply(this, arguments);\n };\n return eve.on(name, f2);\n };\n /*\\\n * eve.version\n [ property (string) ]\n **\n * Current version of the library.\n \\*/\n eve.version = version;\n eve.toString = function () {\n return \"You are running Eve \" + version;\n };\n ( true && module.exports) ? (module.exports = eve) : ( true ? (!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() { return eve; }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))) : (undefined));\n})(this);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZXZlLXJhcGhhZWwvZXZlLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vUmFwaGFlbC8uL25vZGVfbW9kdWxlcy9ldmUtcmFwaGFlbC9ldmUuanM/ZDJiNCJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTMgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vIFxuLy8gaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4vLyBcbi8vIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbi8vIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbi8vIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuLy8gbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4vLyDilIzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJAgXFxcXFxuLy8g4pSCIEV2ZSAwLjUuMCAtIEphdmFTY3JpcHQgRXZlbnRzIExpYnJhcnkgICAgICAgICAgICAgICAgICAgICAg4pSCIFxcXFxcbi8vIOKUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpCBcXFxcXG4vLyDilIIgQXV0aG9yIERtaXRyeSBCYXJhbm92c2tpeSAoaHR0cDovL2RtaXRyeS5iYXJhbm92c2tpeS5jb20vKSDilIIgXFxcXFxuLy8g4pSU4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSYIFxcXFxcblxuKGZ1bmN0aW9uIChnbG9iKSB7XG4gICAgdmFyIHZlcnNpb24gPSBcIjAuNS4wXCIsXG4gICAgICAgIGhhcyA9IFwiaGFzT3duUHJvcGVydHlcIixcbiAgICAgICAgc2VwYXJhdG9yID0gL1tcXC5cXC9dLyxcbiAgICAgICAgY29tYXNlcGFyYXRvciA9IC9cXHMqLFxccyovLFxuICAgICAgICB3aWxkY2FyZCA9IFwiKlwiLFxuICAgICAgICBmdW4gPSBmdW5jdGlvbiAoKSB7fSxcbiAgICAgICAgbnVtc29ydCA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gYSAtIGI7XG4gICAgICAgIH0sXG4gICAgICAgIGN1cnJlbnRfZXZlbnQsXG4gICAgICAgIHN0b3AsXG4gICAgICAgIGV2ZW50cyA9IHtuOiB7fX0sXG4gICAgICAgIGZpcnN0RGVmaW5lZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRoaXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpc1tpXSAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERlZmluZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgaSA9IHRoaXMubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKC0taSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpc1tpXSAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgb2JqdG9zID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyxcbiAgICAgICAgU3RyID0gU3RyaW5nLFxuICAgICAgICBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAoYXIpIHtcbiAgICAgICAgICAgIHJldHVybiBhciBpbnN0YW5jZW9mIEFycmF5IHx8IG9ianRvcy5jYWxsKGFyKSA9PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZVxuICAgICBbIG1ldGhvZCBdXG5cbiAgICAgKiBGaXJlcyBldmVudCB3aXRoIGdpdmVuIGBuYW1lYCwgZ2l2ZW4gc2NvcGUgYW5kIG90aGVyIHBhcmFtZXRlcnMuXG5cbiAgICAgPiBBcmd1bWVudHNcblxuICAgICAtIG5hbWUgKHN0cmluZykgbmFtZSBvZiB0aGUgKmV2ZW50KiwgZG90IChgLmApIG9yIHNsYXNoIChgL2ApIHNlcGFyYXRlZFxuICAgICAtIHNjb3BlIChvYmplY3QpIGNvbnRleHQgZm9yIHRoZSBldmVudCBoYW5kbGVyc1xuICAgICAtIHZhcmFyZ3MgKC4uLikgdGhlIHJlc3Qgb2YgYXJndW1lbnRzIHdpbGwgYmUgc2VudCB0byBldmVudCBoYW5kbGVyc1xuXG4gICAgID0gKG9iamVjdCkgYXJyYXkgb2YgcmV0dXJuZWQgdmFsdWVzIGZyb20gdGhlIGxpc3RlbmVycy4gQXJyYXkgaGFzIHR3byBtZXRob2RzIGAuZmlyc3REZWZpbmVkKClgIGFuZCBgLmxhc3REZWZpbmVkKClgIHRvIGdldCBmaXJzdCBvciBsYXN0IG5vdCBgdW5kZWZpbmVkYCB2YWx1ZS5cbiAgICBcXCovXG4gICAgICAgIHZhciBldmUgPSBmdW5jdGlvbiAobmFtZSwgc2NvcGUpIHtcbiAgICAgICAgICAgIHZhciBlID0gZXZlbnRzLFxuICAgICAgICAgICAgICAgIG9sZHN0b3AgPSBzdG9wLFxuICAgICAgICAgICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLFxuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGV2ZS5saXN0ZW5lcnMobmFtZSksXG4gICAgICAgICAgICAgICAgeiA9IDAsXG4gICAgICAgICAgICAgICAgZiA9IGZhbHNlLFxuICAgICAgICAgICAgICAgIGwsXG4gICAgICAgICAgICAgICAgaW5kZXhlZCA9IFtdLFxuICAgICAgICAgICAgICAgIHF1ZXVlID0ge30sXG4gICAgICAgICAgICAgICAgb3V0ID0gW10sXG4gICAgICAgICAgICAgICAgY2UgPSBjdXJyZW50X2V2ZW50LFxuICAgICAgICAgICAgICAgIGVycm9ycyA9IFtdO1xuICAgICAgICAgICAgb3V0LmZpcnN0RGVmaW5lZCA9IGZpcnN0RGVmaW5lZDtcbiAgICAgICAgICAgIG91dC5sYXN0RGVmaW5lZCA9IGxhc3REZWZpbmVkO1xuICAgICAgICAgICAgY3VycmVudF9ldmVudCA9IG5hbWU7XG4gICAgICAgICAgICBzdG9wID0gMDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBpaTsgaSsrKSBpZiAoXCJ6SW5kZXhcIiBpbiBsaXN0ZW5lcnNbaV0pIHtcbiAgICAgICAgICAgICAgICBpbmRleGVkLnB1c2gobGlzdGVuZXJzW2ldLnpJbmRleCk7XG4gICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS56SW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHF1ZXVlW2xpc3RlbmVyc1tpXS56SW5kZXhdID0gbGlzdGVuZXJzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGluZGV4ZWQuc29ydChudW1zb3J0KTtcbiAgICAgICAgICAgIHdoaWxlIChpbmRleGVkW3pdIDwgMCkge1xuICAgICAgICAgICAgICAgIGwgPSBxdWV1ZVtpbmRleGVkW3orK11dO1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKGwuYXBwbHkoc2NvcGUsIGFyZ3MpKTtcbiAgICAgICAgICAgICAgICBpZiAoc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICBzdG9wID0gb2xkc3RvcDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgIGwgPSBsaXN0ZW5lcnNbaV07XG4gICAgICAgICAgICAgICAgaWYgKFwiekluZGV4XCIgaW4gbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobC56SW5kZXggPT0gaW5kZXhlZFt6XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB6Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbCA9IHF1ZXVlW2luZGV4ZWRbel1dO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgJiYgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKGwpXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBxdWV1ZVtsLnpJbmRleF0gPSBsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0LnB1c2gobC5hcHBseShzY29wZSwgYXJncykpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdG9wID0gb2xkc3RvcDtcbiAgICAgICAgICAgIGN1cnJlbnRfZXZlbnQgPSBjZTtcbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFVuZG9jdW1lbnRlZC4gRGVidWcgb25seS5cbiAgICAgICAgZXZlLl9ldmVudHMgPSBldmVudHM7XG4gICAgLypcXFxuICAgICAqIGV2ZS5saXN0ZW5lcnNcbiAgICAgWyBtZXRob2QgXVxuXG4gICAgICogSW50ZXJuYWwgbWV0aG9kIHdoaWNoIGdpdmVzIHlvdSBhcnJheSBvZiBhbGwgZXZlbnQgaGFuZGxlcnMgdGhhdCB3aWxsIGJlIHRyaWdnZXJlZCBieSB0aGUgZ2l2ZW4gYG5hbWVgLlxuXG4gICAgID4gQXJndW1lbnRzXG5cbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkXG5cbiAgICAgPSAoYXJyYXkpIGFycmF5IG9mIGV2ZW50IGhhbmRsZXJzXG4gICAgXFwqL1xuICAgIGV2ZS5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gbmFtZSA6IG5hbWUuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgIGUgPSBldmVudHMsXG4gICAgICAgICAgICBpdGVtLFxuICAgICAgICAgICAgaXRlbXMsXG4gICAgICAgICAgICBrLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGlpLFxuICAgICAgICAgICAgaixcbiAgICAgICAgICAgIGpqLFxuICAgICAgICAgICAgbmVzLFxuICAgICAgICAgICAgZXMgPSBbZV0sXG4gICAgICAgICAgICBvdXQgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBuYW1lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBuZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZXMubGVuZ3RoOyBqIDwgamo7IGorKykge1xuICAgICAgICAgICAgICAgIGUgPSBlc1tqXS5uO1xuICAgICAgICAgICAgICAgIGl0ZW1zID0gW2VbbmFtZXNbaV1dLCBlW3dpbGRjYXJkXV07XG4gICAgICAgICAgICAgICAgayA9IDI7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGstLSkge1xuICAgICAgICAgICAgICAgICAgICBpdGVtID0gaXRlbXNba107XG4gICAgICAgICAgICAgICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXMucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IG91dC5jb25jYXQoaXRlbS5mIHx8IFtdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVzID0gbmVzO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogZXZlLnNlcGFyYXRvclxuICAgICBbIG1ldGhvZCBdXG5cbiAgICAgKiBJZiBmb3Igc29tZSByZWFzb25zIHlvdSBkb27igJl0IGxpa2UgZGVmYXVsdCBzZXBhcmF0b3JzIChgLmAgb3IgYC9gKSB5b3UgY2FuIHNwZWNpZnkgeW91cnNcbiAgICAgKiBoZXJlLiBCZSBhd2FyZSB0aGF0IGlmIHlvdSBwYXNzIGEgc3RyaW5nIGxvbmdlciB0aGFuIG9uZSBjaGFyYWN0ZXIgaXQgd2lsbCBiZSB0cmVhdGVkIGFzXG4gICAgICogYSBsaXN0IG9mIGNoYXJhY3RlcnMuXG5cbiAgICAgLSBzZXBhcmF0b3IgKHN0cmluZykgbmV3IHNlcGFyYXRvci4gRW1wdHkgc3RyaW5nIHJlc2V0cyB0byBkZWZhdWx0OiBgLmAgb3IgYC9gLlxuICAgIFxcKi9cbiAgICBldmUuc2VwYXJhdG9yID0gZnVuY3Rpb24gKHNlcCkge1xuICAgICAgICBpZiAoc2VwKSB7XG4gICAgICAgICAgICBzZXAgPSBTdHIoc2VwKS5yZXBsYWNlKC8oPz1bXFwuXFxeXFxdXFxbXFwtXSkvZywgXCJcXFxcXCIpO1xuICAgICAgICAgICAgc2VwID0gXCJbXCIgKyBzZXAgKyBcIl1cIjtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlcGFyYXRvciA9IC9bXFwuXFwvXS87XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBldmUub25cbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEJpbmRzIGdpdmVuIGV2ZW50IGhhbmRsZXIgd2l0aCBhIGdpdmVuIG5hbWUuIFlvdSBjYW4gdXNlIHdpbGRjYXJkcyDigJxgKmDigJ0gZm9yIHRoZSBuYW1lczpcbiAgICAgfCBldmUub24oXCIqLnVuZGVyLipcIiwgZik7XG4gICAgIHwgZXZlKFwibW91c2UudW5kZXIuZmxvb3JcIik7IC8vIHRyaWdnZXJzIGZcbiAgICAgKiBVc2UgQGV2ZSB0byB0cmlnZ2VyIHRoZSBsaXN0ZW5lci5cbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICoqXG4gICAgIC0gbmFtZSAoYXJyYXkpIGlmIHlvdSBkb27igJl0IHdhbnQgdG8gdXNlIHNlcGFyYXRvcnMsIHlvdSBjYW4gdXNlIGFycmF5IG9mIHN0cmluZ3NcbiAgICAgLSBmIChmdW5jdGlvbikgZXZlbnQgaGFuZGxlciBmdW5jdGlvblxuICAgICAqKlxuICAgICA9IChmdW5jdGlvbikgcmV0dXJuZWQgZnVuY3Rpb24gYWNjZXB0cyBhIHNpbmdsZSBudW1lcmljIHBhcmFtZXRlciB0aGF0IHJlcHJlc2VudHMgei1pbmRleCBvZiB0aGUgaGFuZGxlci4gSXQgaXMgYW4gb3B0aW9uYWwgZmVhdHVyZSBhbmQgb25seSB1c2VkIHdoZW4geW91IG5lZWQgdG8gZW5zdXJlIHRoYXQgc29tZSBzdWJzZXQgb2YgaGFuZGxlcnMgd2lsbCBiZSBpbnZva2VkIGluIGEgZ2l2ZW4gb3JkZXIsIGRlc3BpdGUgb2YgdGhlIG9yZGVyIG9mIGFzc2lnbm1lbnQuIFxuICAgICA+IEV4YW1wbGU6XG4gICAgIHwgZXZlLm9uKFwibW91c2VcIiwgZWF0SXQpKDIpO1xuICAgICB8IGV2ZS5vbihcIm1vdXNlXCIsIHNjcmVhbSk7XG4gICAgIHwgZXZlLm9uKFwibW91c2VcIiwgY2F0Y2hJdCkoMSk7XG4gICAgICogVGhpcyB3aWxsIGVuc3VyZSB0aGF0IGBjYXRjaEl0YCBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBiZWZvcmUgYGVhdEl0YC5cbiAgICAgKlxuICAgICAqIElmIHlvdSB3YW50IHRvIHB1dCB5b3VyIGhhbmRsZXIgYmVmb3JlIG5vbi1pbmRleGVkIGhhbmRsZXJzLCBzcGVjaWZ5IGEgbmVnYXRpdmUgdmFsdWUuXG4gICAgICogTm90ZTogSSBhc3N1bWUgbW9zdCBvZiB0aGUgdGltZSB5b3UgZG9u4oCZdCBuZWVkIHRvIHdvcnJ5IGFib3V0IHotaW5kZXgsIGJ1dCBpdOKAmXMgbmljZSB0byBoYXZlIHRoaXMgZmVhdHVyZSDigJxqdXN0IGluIGNhc2XigJ0uXG4gICAgXFwqL1xuICAgIGV2ZS5vbiA9IGZ1bmN0aW9uIChuYW1lLCBmKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZiAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gKGlzQXJyYXkobmFtZVswXSkgPyBuYW1lIDogW25hbWVdKSA6IFN0cihuYW1lKS5zcGxpdChjb21hc2VwYXJhdG9yKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5hbWVzID0gaXNBcnJheShuYW1lKSA/IG5hbWUgOiBTdHIobmFtZSkuc3BsaXQoc2VwYXJhdG9yKSxcbiAgICAgICAgICAgICAgICAgICAgZSA9IGV2ZW50cyxcbiAgICAgICAgICAgICAgICAgICAgZXhpc3Q7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBlID0gZS5uO1xuICAgICAgICAgICAgICAgICAgICBlID0gZS5oYXNPd25Qcm9wZXJ0eShuYW1lc1tpXSkgJiYgZVtuYW1lc1tpXV0gfHwgKGVbbmFtZXNbaV1dID0ge246IHt9fSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGUuZiA9IGUuZiB8fCBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGUuZi5sZW5ndGg7IGkgPCBpaTsgaSsrKSBpZiAoZS5mW2ldID09IGYpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhpc3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgIWV4aXN0ICYmIGUuZi5wdXNoKGYpO1xuICAgICAgICAgICAgfShuYW1lc1tpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoekluZGV4KSB7XG4gICAgICAgICAgICBpZiAoK3pJbmRleCA9PSArekluZGV4KSB7XG4gICAgICAgICAgICAgICAgZi56SW5kZXggPSArekluZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5mXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBSZXR1cm5zIGZ1bmN0aW9uIHRoYXQgd2lsbCBmaXJlIGdpdmVuIGV2ZW50IHdpdGggb3B0aW9uYWwgYXJndW1lbnRzLlxuICAgICAqIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIHRvIHRoZSByZXN1bHQgZnVuY3Rpb24gd2lsbCBiZSBhbHNvXG4gICAgICogY29uY2F0ZWQgdG8gdGhlIGxpc3Qgb2YgZmluYWwgYXJndW1lbnRzLlxuICAgICB8IGVsLm9uY2xpY2sgPSBldmUuZihcImNsaWNrXCIsIDEsIDIpO1xuICAgICB8IGV2ZS5vbihcImNsaWNrXCIsIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgIHwgICAgIGNvbnNvbGUubG9nKGEsIGIsIGMpOyAvLyAxLCAyLCBbZXZlbnQgb2JqZWN0XVxuICAgICB8IH0pO1xuICAgICA+IEFyZ3VtZW50c1xuICAgICAtIGV2ZW50IChzdHJpbmcpIGV2ZW50IG5hbWVcbiAgICAgLSB2YXJhcmdzICjigKYpIGFuZCBhbnkgb3RoZXIgYXJndW1lbnRzXG4gICAgID0gKGZ1bmN0aW9uKSBwb3NzaWJsZSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgXFwqL1xuICAgIGV2ZS5mID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBhdHRycyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGV2ZS5hcHBseShudWxsLCBbZXZlbnQsIG51bGxdLmNvbmNhdChhdHRycykuY29uY2F0KFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSkpO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5zdG9wXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBJcyB1c2VkIGluc2lkZSBhbiBldmVudCBoYW5kbGVyIHRvIHN0b3AgdGhlIGV2ZW50LCBwcmV2ZW50aW5nIGFueSBzdWJzZXF1ZW50IGxpc3RlbmVycyBmcm9tIGZpcmluZy5cbiAgICBcXCovXG4gICAgZXZlLnN0b3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHN0b3AgPSAxO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5udFxuICAgICBbIG1ldGhvZCBdXG4gICAgICoqXG4gICAgICogQ291bGQgYmUgdXNlZCBpbnNpZGUgZXZlbnQgaGFuZGxlciB0byBmaWd1cmUgb3V0IGFjdHVhbCBuYW1lIG9mIHRoZSBldmVudC5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBzdWJuYW1lIChzdHJpbmcpICNvcHRpb25hbCBzdWJuYW1lIG9mIHRoZSBldmVudFxuICAgICAqKlxuICAgICA9IChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBpZiBgc3VibmFtZWAgaXMgbm90IHNwZWNpZmllZFxuICAgICAqIG9yXG4gICAgID0gKGJvb2xlYW4pIGB0cnVlYCwgaWYgY3VycmVudCBldmVudOKAmXMgbmFtZSBjb250YWlucyBgc3VibmFtZWBcbiAgICBcXCovXG4gICAgZXZlLm50ID0gZnVuY3Rpb24gKHN1Ym5hbWUpIHtcbiAgICAgICAgdmFyIGN1ciA9IGlzQXJyYXkoY3VycmVudF9ldmVudCkgPyBjdXJyZW50X2V2ZW50LmpvaW4oXCIuXCIpIDogY3VycmVudF9ldmVudDtcbiAgICAgICAgaWYgKHN1Ym5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKD86XFxcXC58XFxcXC98XilcIiArIHN1Ym5hbWUgKyBcIig/OlxcXFwufFxcXFwvfCQpXCIpLnRlc3QoY3VyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3VyO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5udHNcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIENvdWxkIGJlIHVzZWQgaW5zaWRlIGV2ZW50IGhhbmRsZXIgdG8gZmlndXJlIG91dCBhY3R1YWwgbmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgICoqXG4gICAgICoqXG4gICAgID0gKGFycmF5KSBuYW1lcyBvZiB0aGUgZXZlbnRcbiAgICBcXCovXG4gICAgZXZlLm50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkoY3VycmVudF9ldmVudCkgPyBjdXJyZW50X2V2ZW50IDogY3VycmVudF9ldmVudC5zcGxpdChzZXBhcmF0b3IpO1xuICAgIH07XG4gICAgLypcXFxuICAgICAqIGV2ZS5vZmZcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIFJlbW92ZXMgZ2l2ZW4gZnVuY3Rpb24gZnJvbSB0aGUgbGlzdCBvZiBldmVudCBsaXN0ZW5lcnMgYXNzaWduZWQgdG8gZ2l2ZW4gbmFtZS5cbiAgICAgKiBJZiBubyBhcmd1bWVudHMgc3BlY2lmaWVkIGFsbCB0aGUgZXZlbnRzIHdpbGwgYmUgY2xlYXJlZC5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgXFwqL1xuICAgIC8qXFxcbiAgICAgKiBldmUudW5iaW5kXG4gICAgIFsgbWV0aG9kIF1cbiAgICAgKipcbiAgICAgKiBTZWUgQGV2ZS5vZmZcbiAgICBcXCovXG4gICAgZXZlLm9mZiA9IGV2ZS51bmJpbmQgPSBmdW5jdGlvbiAobmFtZSwgZikge1xuICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgIGV2ZS5fZXZlbnRzID0gZXZlbnRzID0ge246IHt9fTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmFtZXMgPSBpc0FycmF5KG5hbWUpID8gKGlzQXJyYXkobmFtZVswXSkgPyBuYW1lIDogW25hbWVdKSA6IFN0cihuYW1lKS5zcGxpdChjb21hc2VwYXJhdG9yKTtcbiAgICAgICAgaWYgKG5hbWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IG5hbWVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHtcbiAgICAgICAgICAgICAgICBldmUub2ZmKG5hbWVzW2ldLCBmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBuYW1lcyA9IGlzQXJyYXkobmFtZSkgPyBuYW1lIDogU3RyKG5hbWUpLnNwbGl0KHNlcGFyYXRvcik7XG4gICAgICAgIHZhciBlLFxuICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgc3BsaWNlLFxuICAgICAgICAgICAgaSwgaWksIGosIGpqLFxuICAgICAgICAgICAgY3VyID0gW2V2ZW50c107XG4gICAgICAgIGZvciAoaSA9IDAsIGlpID0gbmFtZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGN1ci5sZW5ndGg7IGogKz0gc3BsaWNlLmxlbmd0aCAtIDIpIHtcbiAgICAgICAgICAgICAgICBzcGxpY2UgPSBbaiwgMV07XG4gICAgICAgICAgICAgICAgZSA9IGN1cltqXS5uO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lc1tpXSAhPSB3aWxkY2FyZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZVtuYW1lc1tpXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwbGljZS5wdXNoKGVbbmFtZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIGUpIGlmIChlW2hhc10oa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3BsaWNlLnB1c2goZVtrZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjdXIuc3BsaWNlLmFwcGx5KGN1ciwgc3BsaWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGN1ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICAgICAgICBlID0gY3VyW2ldO1xuICAgICAgICAgICAgd2hpbGUgKGUubikge1xuICAgICAgICAgICAgICAgIGlmIChmKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZS5mLmxlbmd0aDsgaiA8IGpqOyBqKyspIGlmIChlLmZbal0gPT0gZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuZi5zcGxpY2UoaiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAhZS5mLmxlbmd0aCAmJiBkZWxldGUgZS5mO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIGUubikgaWYgKGUubltoYXNdKGtleSkgJiYgZS5uW2tleV0uZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bmNzID0gZS5uW2tleV0uZjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gZnVuY3MubGVuZ3RoOyBqIDwgamo7IGorKykgaWYgKGZ1bmNzW2pdID09IGYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jcy5zcGxpY2UoaiwgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAhZnVuY3MubGVuZ3RoICYmIGRlbGV0ZSBlLm5ba2V5XS5mO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGUuZjtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChrZXkgaW4gZS5uKSBpZiAoZS5uW2hhc10oa2V5KSAmJiBlLm5ba2V5XS5mKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgZS5uW2tleV0uZjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlID0gZS5uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvKlxcXG4gICAgICogZXZlLm9uY2VcbiAgICAgWyBtZXRob2QgXVxuICAgICAqKlxuICAgICAqIEJpbmRzIGdpdmVuIGV2ZW50IGhhbmRsZXIgd2l0aCBhIGdpdmVuIG5hbWUgdG8gb25seSBydW4gb25jZSB0aGVuIHVuYmluZCBpdHNlbGYuXG4gICAgIHwgZXZlLm9uY2UoXCJsb2dpblwiLCBmKTtcbiAgICAgfCBldmUoXCJsb2dpblwiKTsgLy8gdHJpZ2dlcnMgZlxuICAgICB8IGV2ZShcImxvZ2luXCIpOyAvLyBubyBsaXN0ZW5lcnNcbiAgICAgKiBVc2UgQGV2ZSB0byB0cmlnZ2VyIHRoZSBsaXN0ZW5lci5cbiAgICAgKipcbiAgICAgPiBBcmd1bWVudHNcbiAgICAgKipcbiAgICAgLSBuYW1lIChzdHJpbmcpIG5hbWUgb2YgdGhlIGV2ZW50LCBkb3QgKGAuYCkgb3Igc2xhc2ggKGAvYCkgc2VwYXJhdGVkLCB3aXRoIG9wdGlvbmFsIHdpbGRjYXJkc1xuICAgICAtIGYgKGZ1bmN0aW9uKSBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICoqXG4gICAgID0gKGZ1bmN0aW9uKSBzYW1lIHJldHVybiBmdW5jdGlvbiBhcyBAZXZlLm9uXG4gICAgXFwqL1xuICAgIGV2ZS5vbmNlID0gZnVuY3Rpb24gKG5hbWUsIGYpIHtcbiAgICAgICAgdmFyIGYyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXZlLm9mZihuYW1lLCBmMik7XG4gICAgICAgICAgICByZXR1cm4gZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZXZlLm9uKG5hbWUsIGYyKTtcbiAgICB9O1xuICAgIC8qXFxcbiAgICAgKiBldmUudmVyc2lvblxuICAgICBbIHByb3BlcnR5IChzdHJpbmcpIF1cbiAgICAgKipcbiAgICAgKiBDdXJyZW50IHZlcnNpb24gb2YgdGhlIGxpYnJhcnkuXG4gICAgXFwqL1xuICAgIGV2ZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICBldmUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIllvdSBhcmUgcnVubmluZyBFdmUgXCIgKyB2ZXJzaW9uO1xuICAgIH07XG4gICAgKHR5cGVvZiBtb2R1bGUgIT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cykgPyAobW9kdWxlLmV4cG9ydHMgPSBldmUpIDogKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kID8gKGRlZmluZShcImV2ZVwiLCBbXSwgZnVuY3Rpb24oKSB7IHJldHVybiBldmU7IH0pKSA6IChnbG9iLmV2ZSA9IGV2ZSkpO1xufSkodGhpcyk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/eve-raphael/eve.js\n"); 57624 57625/***/ })
57625 57626 57627/******/ }); 57628}); 57629/* @license 57630morris.js v0.5.0 57631Copyright 2014 Olly Smith All rights reserved. 57632Licensed under the BSD-2-Clause License. 57633*/ 57634 57635 57636(function() { 57637 var $, Morris, minutesSpecHelper, secondsSpecHelper, 57638 __slice = [].slice, 57639 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 57640 __hasProp = {}.hasOwnProperty, 57641 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, 57642 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 57643 57644 Morris = window.Morris = {}; 57645 57646 $ = jQuery; 57647 57648 Morris.EventEmitter = (function() { 57649 function EventEmitter() {} 57650 57651 EventEmitter.prototype.on = function(name, handler) { 57652 if (this.handlers == null) { 57653 this.handlers = {}; 57654 } 57655 if (this.handlers[name] == null) { 57656 this.handlers[name] = []; 57657 } 57658 this.handlers[name].push(handler); 57659 return this; 57660 }; 57661 57662 EventEmitter.prototype.fire = function() { 57663 var args, handler, name, _i, _len, _ref, _results; 57664 name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 57665 if ((this.handlers != null) && (this.handlers[name] != null)) { 57666 _ref = this.handlers[name]; 57667 _results = []; 57668 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 57669 handler = _ref[_i]; 57670 _results.push(handler.apply(null, args)); 57671 } 57672 return _results; 57673 } 57674 }; 57675 57676 return EventEmitter; 57677 57678 })(); 57679 57680 Morris.commas = function(num) { 57681 var absnum, intnum, ret, strabsnum; 57682 if (num != null) { 57683 ret = num < 0 ? "-" : ""; 57684 absnum = Math.abs(num); 57685 intnum = Math.floor(absnum).toFixed(0); 57686 ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ','); 57687 strabsnum = absnum.toString(); 57688 if (strabsnum.length > intnum.length) { 57689 ret += strabsnum.slice(intnum.length); 57690 } 57691 return ret; 57692 } else { 57693 return '-'; 57694 } 57695 }; 57696 57697 Morris.pad2 = function(number) { 57698 return (number < 10 ? '0' : '') + number; 57699 }; 57700 57701 Morris.Grid = (function(_super) { 57702 __extends(Grid, _super); 57703 57704 function Grid(options) { 57705 this.resizeHandler = __bind(this.resizeHandler, this); 57706 var _this = this; 57707 if (typeof options.element === 'string') { 57708 this.el = $(document.getElementById(options.element)); 57709 } else { 57710 this.el = $(options.element); 57711 } 57712 if ((this.el == null) || this.el.length === 0) { 57713 throw new Error("Graph container element not found"); 57714 } 57715 if (this.el.css('position') === 'static') { 57716 this.el.css('position', 'relative'); 57717 } 57718 this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options); 57719 if (typeof this.options.units === 'string') { 57720 this.options.postUnits = options.units; 57721 } 57722 this.raphael = new Raphael(this.el[0]); 57723 this.elementWidth = null; 57724 this.elementHeight = null; 57725 this.dirty = false; 57726 this.selectFrom = null; 57727 if (this.init) { 57728 this.init(); 57729 } 57730 this.setData(this.options.data); 57731 this.el.bind('mousemove', function(evt) { 57732 var left, offset, right, width, x; 57733 offset = _this.el.offset(); 57734 x = evt.pageX - offset.left; 57735 if (_this.selectFrom) { 57736 left = _this.data[_this.hitTest(Math.min(x, _this.selectFrom))]._x; 57737 right = _this.data[_this.hitTest(Math.max(x, _this.selectFrom))]._x; 57738 width = right - left; 57739 return _this.selectionRect.attr({ 57740 x: left, 57741 width: width 57742 }); 57743 } else { 57744 return _this.fire('hovermove', x, evt.pageY - offset.top); 57745 } 57746 }); 57747 this.el.bind('mouseleave', function(evt) { 57748 if (_this.selectFrom) { 57749 _this.selectionRect.hide(); 57750 _this.selectFrom = null; 57751 } 57752 return _this.fire('hoverout'); 57753 }); 57754 this.el.bind('touchstart touchmove touchend', function(evt) { 57755 var offset, touch; 57756 touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0]; 57757 offset = _this.el.offset(); 57758 return _this.fire('hovermove', touch.pageX - offset.left, touch.pageY - offset.top); 57759 }); 57760 this.el.bind('click', function(evt) { 57761 var offset; 57762 offset = _this.el.offset(); 57763 return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top); 57764 }); 57765 if (this.options.rangeSelect) { 57766 this.selectionRect = this.raphael.rect(0, 0, 0, this.el.innerHe
57766ight()).attr({ 57767 fill: this.options.rangeSelectColor, 57768 stroke: false 57769 }).toBack().hide(); 57770 this.el.bind('mousedown', function(evt) { 57771 var offset; 57772 offset = _this.el.offset(); 57773 return _this.startRange(evt.pageX - offset.left); 57774 }); 57775 this.el.bind('mouseup', function(evt) { 57776 var offset; 57777 offset = _this.el.offset(); 57778 _this.endRange(evt.pageX - offset.left); 57779 return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top); 57780 }); 57781 } 57782 if (this.options.resize) { 57783 $(window).bind('resize', function(evt) { 57784 if (_this.timeoutId != null) { 57785 window.clearTimeout(_this.timeoutId); 57786 } 57787 return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100); 57788 }); 57789 } 57790 this.el.css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)'); 57791 if (this.postInit) { 57792 this.postInit(); 57793 } 57794 } 57795 57796 Grid.prototype.gridDefaults = { 57797 dateFormat: null, 57798 axes: true, 57799 grid: true, 57800 gridLineColor: '#aaa', 57801 gridStrokeWidth: 0.5, 57802 gridTextColor: '#888', 57803 gridTextSize: 12, 57804 gridTextFamily: 'sans-serif', 57805 gridTextWeight: 'normal', 57806 hideHover: false, 57807 yLabelFormat: null, 57808 xLabelAngle: 0, 57809 numLines: 5, 57810 padding: 25, 57811 parseTime: true, 57812 postUnits: '', 57813 preUnits: '', 57814 ymax: 'auto', 57815 ymin: 'auto 0', 57816 goals: [], 57817 goalStrokeWidth: 1.0, 57818 goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'], 57819 events: [], 57820 eventStrokeWidth: 1.0, 57821 eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'], 57822 rangeSelect: null, 57823 rangeSelectColor: '#eef', 57824 resize: false 57825 }; 57826 57827 Grid.prototype.setData = function(data, redraw) { 57828 var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval, _ref; 57829 if (redraw == null) { 57830 redraw = true; 57831 } 57832 this.options.data = data; 57833 if ((data == null) || data.length === 0) { 57834 this.data = []; 57835 this.raphael.clear(); 57836 if (this.hover != null) { 57837 this.hover.hide(); 57838 } 57839 return; 57840 } 57841 ymax = this.cumulative ? 0 : null; 57842 ymin = this.cumulative ? 0 : null; 57843 if (this.options.goals.length > 0) { 57844 minGoal = Math.min.apply(Math, this.options.goals); 57845 maxGoal = Math.max.apply(Math, this.options.goals); 57846 ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal; 57847 ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal; 57848 } 57849 this.data = (function() { 57850 var _i, _len, _results; 57851 _results = []; 57852 for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) { 57853 row = data[index]; 57854 ret = { 57855 src: row 57856 }; 57857 ret.label = row[this.options.xkey]; 57858 if (this.options.parseTime) { 57859 ret.x = Morris.parseDate(ret.label); 57860 if (this.options.dateFormat) { 57861 ret.label = this.options.dateFormat(ret.x); 57862 } else if (typeof ret.label === 'number') { 57863 ret.label = new Date(ret.label).toString(); 57864 } 57865 } else { 57866 ret.x = index; 57867 if (this.options.xLabelFormat) { 57868 ret.label = this.options.xLabelFormat(ret); 57869 } 57870 } 57871 total = 0; 57872 ret.y = (function() { 57873 var _j, _len1, _ref, _results1; 57874 _ref = this.options.ykeys; 57875 _results1 = []; 57876 for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) { 57877 ykey = _ref[idx]; 57878 yval = row[ykey]; 57879 if (typeof yval === 'string') { 57880 yval = parseFloat(yval); 57881 } 57882 if ((yval != null) && typeof yval !== 'number') { 57883 yval = null; 57884 } 57885 if (yval != null) { 57886 if (this.cumulative) { 57887 total += yval; 57888 } else { 57889 if (ymax != null) { 57890 ymax = Math.max(yval, ymax); 57891 ymin = Math.min(yval, ymin); 57892 } else { 57893 ymax = ymin = yval; 57894 } 57895 } 57896 } 57897 if (this.cumulative && (total != null)) { 57898 ymax = Math.max(total, ymax); 57899 ymin = Math.min(total, ymin); 57900 } 57901 _results1.push(yval); 57902 } 57903 return _results1; 57904 }).call(this); 57905 _results.push(ret); 57906 } 57907 return _results; 57908 }).call(this); 57909 if (this.options.parseTime) { 57910 this.data = this.data.sort(function(a, b) { 57911 return (a.x > b.x) - (b.x > a.x); 57912 }); 57913 } 57914 this.xmin = this.data[0].x; 57915 this.xmax = this.data[this.data.length - 1].x; 57916 this.events = []; 57917 if (this.options.events.length > 0) { 57918 if (this.options.parseTime) { 57919 this.events = (function() { 57920 var _i, _len, _ref, _results; 57921 _ref = this.options.events; 57922 _results = []; 57923 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 57924 e = _ref[_i]; 57925 _results.push(Morris.parseDate(e)); 57926 } 57927 return _results; 57928 }).call(this); 57929 } else { 57930 this.events = this.options.events; 57931 } 57932 this.xmax = Math.max(this.xmax, Math.max.apply(Math, this.events)); 57933 this.xmin = Math.min(this.xmin, Math.min.apply(Math, this.events)); 57934 } 57935 if (this.xmin === this.xmax) { 57936 this.xmin -= 1; 57937 this.xmax += 1; 57938 } 57939 this.ymin = this.yboundary('min', ymin); 57940 this.ymax = this.yboundary('max', ymax); 57941 if (this.ymin === this.ymax) { 57942 if (ymin) { 57943 this.ymin -= 1; 57944 } 57945 this.ymax += 1; 57946 } 57947 if (((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') || this.options.grid === true) { 57948 if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) { 57949 this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines); 57950 this.ymin = Math.min(this.ymin, this.grid[0]); 57951 this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]); 57952 } else { 57953 step = (this.ymax - this.ymin) / (this.options.numLines - 1); 57954 this.grid = (function() { 57955 var _i, _ref1, _ref2, _results; 57956 _results = []; 57957 for (y = _i = _ref1 = this.ymin, _ref2 = this.ymax; step > 0 ? _i <= _ref2 : _i >= _ref2; y = _i += step) { 57958 _results.push(y); 57959 } 57960 return _results; 57961 }).call(this); 57962 } 57963 } 57964 this.dirty = true; 57965 if (redraw) { 57966 return this.redraw(); 57967 } 57968 }; 57969
57970 Grid.prototype.yboundary = function(boundaryType, currentValue) { 57971 var boundaryOption, suggestedValue; 57972 boundaryOption = this.options["y" + boundaryType]; 57973 if (typeof boundaryOption === 'string') { 57974 if (boundaryOption.slice(0, 4) === 'auto') { 57975 if (boundaryOption.length > 5) { 57976 suggestedValue = parseInt(boundaryOption.slice(5), 10); 57977 if (currentValue == null) { 57978 return suggestedValue; 57979 } 57980 return Math[boundaryType](currentValue, suggestedValue); 57981 } else { 57982 if (currentValue != null) { 57983 return currentValue; 57984 } else { 57985 return 0; 57986 } 57987 } 57988 } else { 57989 return parseInt(boundaryOption, 10); 57990 } 57991 } else { 57992 return boundaryOption; 57993 } 57994 }; 57995 57996 Grid.prototype.autoGridLines = function(ymin, ymax, nlines) { 57997 var gmax, gmin, grid, smag, span, step, unit, y, ymag; 57998 span = ymax - ymin; 57999 ymag = Math.floor(Math.log(span) / Math.log(10)); 58000 unit = Math.pow(10, ymag); 58001 gmin = Math.floor(ymin / unit) * unit; 58002 gmax = Math.ceil(ymax / unit) * unit; 58003 step = (gmax - gmin) / (nlines - 1); 58004 if (unit === 1 && step > 1 && Math.ceil(step) !== step) { 58005 step = Math.ceil(step); 58006 gmax = gmin + step * (nlines - 1); 58007 } 58008 if (gmin < 0 && gmax > 0) { 58009 gmin = Math.floor(ymin / step) * step; 58010 gmax = Math.ceil(ymax / step) * step; 58011 } 58012 if (step < 1) { 58013 smag = Math.floor(Math.log(step) / Math.log(10)); 58014 grid = (function() { 58015 var _i, _results; 58016 _results = []; 58017 for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) { 58018 _results.push(parseFloat(y.toFixed(1 - smag))); 58019 } 58020 return _results; 58021 })(); 58022 } else { 58023 grid = (function() { 58024 var _i, _results; 58025 _results = []; 58026 for (y = _i = gmin; step > 0 ? _i <= gmax : _i >= gmax; y = _i += step) { 58027 _results.push(y); 58028 } 58029 return _results; 58030 })(); 58031 } 58032 return grid; 58033 }; 58034 58035 Grid.prototype._calc = function() { 58036 var bottomOffsets, gridLine, h, i, w, yLabelWidths, _ref, _ref1; 58037 w = this.el.width(); 58038 h = this.el.height(); 58039 if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) { 58040 this.elementWidth = w; 58041 this.elementHeight = h; 58042 this.dirty = false; 58043 this.left = this.options.padding; 58044 this.right = this.elementWidth - this.options.padding; 58045 this.top = this.options.padding; 58046 this.bottom = this.elementHeight - this.options.padding; 58047 if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'y') { 58048 yLabelWidths = (function() { 58049 var _i, _len, _ref1, _results; 58050 _ref1 = this.grid; 58051 _results = []; 58052 for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 58053 gridLine = _ref1[_i]; 58054 _results.push(this.measureText(this.yAxisFormat(gridLine)).width); 58055 } 58056 return _results; 58057 }).call(this); 58058 this.left += Math.max.apply(Math, yLabelWidths); 58059 } 58060 if ((_ref1 = this.options.axes) === true || _ref1 === 'both' || _ref1 === 'x') { 58061 bottomOffsets = (function() { 58062 var _i, _ref2, _results; 58063 _results = []; 58064 for (i = _i = 0, _ref2 = this.data.length; 0 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 0 <= _ref2 ? ++_i : --_i) { 58065 _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height); 58066 } 58067 return _results; 58068 }).call(this); 58069 this.bottom -= Math.max.apply(Math, bottomOffsets); 58070 } 58071 this.width = Math.max(1, this.right - this.left); 58072 this.height = Math.max(1, this.bottom - this.top); 58073 this.dx = this.width / (this.xmax - this.xmin); 58074 this.dy = this.height / (this.ymax - this.ymin); 58075 if (this.calc) { 58076 return this.calc(); 58077 } 58078 } 58079 }; 58080 58081 Grid.prototype.transY = function(y) { 58082 return this.bottom - (y - this.ymin) * this.dy; 58083 }; 58084 58085 Grid.prototype.transX = function(x) { 58086 if (this.data.length === 1) { 58087 return (this.left + this.right) / 2; 58088 } else { 58089 return this.left + (x - this.xmin) * this.dx; 58090 } 58091 }; 58092 58093 Grid.prototype.redraw = function() { 58094 this.raphael.clear(); 58095 this._calc();
58096 this.drawGrid(); 58097 this.drawGoals(); 58098 this.drawEvents(); 58099 if (this.draw) { 58100 return this.draw(); 58101 } 58102 }; 58103 58104 Grid.prototype.measureText = function(text, angle) { 58105 var ret, tt; 58106 if (angle == null) { 58107 angle = 0; 58108 } 58109 tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle); 58110 ret = tt.getBBox(); 58111 tt.remove(); 58112 return ret; 58113 }; 58114 58115 Grid.prototype.yAxisFormat = function(label) { 58116 return this.yLabelFormat(label); 58117 }; 58118 58119 Grid.prototype.yLabelFormat = function(label) { 58120 if (typeof this.options.yLabelFormat === 'function') { 58121 return this.options.yLabelFormat(label); 58122 } else { 58123 return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits; 58124 } 58125 }; 58126 58127 Grid.prototype.drawGrid = function() { 58128 var lineY, y, _i, _len, _ref, _ref1, _ref2, _results; 58129 if (this.options.grid === false && ((_ref = this.options.axes) !== true && _ref !== 'both' && _ref !== 'y')) { 58130 return; 58131 } 58132 _ref1 = this.grid; 58133 _results = []; 58134 for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 58135 lineY = _ref1[_i]; 58136 y = this.transY(lineY); 58137 if ((_ref2 = this.options.axes) === true || _ref2 === 'both' || _ref2 === 'y') { 58138 this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY)); 58139 } 58140 if (this.options.grid) { 58141 _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width))); 58142 } else { 58143 _results.push(void 0); 58144 } 58145 } 58146 return _results; 58147 }; 58148 58149 Grid.prototype.drawGoals = function() { 58150 var color, goal, i, _i, _len, _ref, _results; 58151 _ref = this.options.goals; 58152 _results = []; 58153 for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { 58154 goal = _ref[i]; 58155 color = this.options.goalLineColors[i % this.options.goalLineColors.length]; 58156 _results.push(this.drawGoal(goal, color)); 58157 } 58158 return _results; 58159 }; 58160 58161 Grid.prototype.drawEvents = function() { 58162 var color, event, i, _i, _len, _ref, _results; 58163 _ref = this.events; 58164 _results = []; 58165 for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { 58166 event = _ref[i]; 58167 color = this.options.eventLineColors[i % this.options.eventLineColors.length]; 58168 _results.push(this.drawEvent(event, color)); 58169 } 58170 return _results; 58171 }; 58172 58173 Grid.prototype.drawGoal = function(goal, color) { 58174 return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth); 58175 }; 58176 58177 Grid.prototype.drawEvent = function(event, color) { 58178 return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth); 58179 }; 58180 58181 Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) { 58182 return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end'); 58183 }; 58184 58185 Grid.prototype.drawGridLine = function(path) { 58186 return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth); 58187 }; 58188 58189 Grid.prototype.startRange = function(x) { 58190 this.hover.hide(); 58191 this.selectFrom = x; 58192 return this.selectionRect.attr({ 58193 x: x, 58194 width: 0 58195 }).show(); 58196 }; 58197 58198 Grid.prototype.endRange = function(x) { 58199 var end, start; 58200 if (this.selectFrom) { 58201 start = Math.min(this.selectFrom, x); 58202 end = Math.max(this.selectFrom, x); 58203 this.options.rangeSelect.call(this.el, { 58204 start: this.data[this.hitTest(start)].x, 58205 end: this.data[this.hitTest(end)].x 58206 }); 58207 return this.selectFrom = null; 58208 } 58209 }; 58210 58211 Grid.prototype.resizeHandler = function() { 58212 this.timeoutId = null; 58213 this.raphael.setSize(this.el.width(), this.el.height()); 58214 return this.redraw(); 58215 }; 58216 58217 return Grid; 58218 58219 })(Morris.EventEmitter); 58220 58221 Morris.parseDate = function(date) { 58222 var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs; 58223 if (typeof date === 'number') { 58224 return date; 58225 } 58226 m = date.match(/^(\d+) Q(\d)$/); 58227 n = date.match(/^(\d+)-(\d+)$/); 58228 o = date.match(/^(\d+)-(\d+)-(\d+)$/); 58229 p = date.match(/^(\d+) W(\d+)$/); 58230 q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/); 58231 r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/); 58232 if (m) { 58233 return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime(); 58234 } else if (n) { 58235 return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime(); 58236 } else if (o) { 58237 return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime(); 58238 } else if (p) { 58239 ret = new Date(parseInt(p[1], 10), 0, 1); 58240 if (ret.getDay() !== 4) { 58241 ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); 58242 } 58243 return ret.getTime() + parseInt(p[2], 10) * 604800000; 58244 } else if (q) { 58245 if (!q[6]) { 58246 return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime(); 58247 } else { 58248 offsetmins = 0; 58249 if (q[6] !== 'Z') { 58250 offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10); 58251 if (q[7] === '+') { 58252 offsetmins = 0 - offsetmins; 58253 } 58254 } 58255 return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins); 58256 } 58257 } else if (r) { 58258 secs = parseFloat(r[6]); 58259 isecs = Math.floor(secs); 58260 msecs = Math.round((secs - isecs) * 1000); 58261 if (!r[8]) { 58262 return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime(); 58263 } else { 58264 offsetmins = 0; 58265 if (r[8] !== 'Z') { 58266 offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);
58267 if (r[9] === '+') { 58268 offsetmins = 0 - offsetmins; 58269 } 58270 } 58271 return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs); 58272 } 58273 } else { 58274 return new Date(parseInt(date, 10), 0, 1).getTime(); 58275 } 58276 }; 58277 58278 Morris.Hover = (function() { 58279 Hover.defaults = { 58280 "class": 'morris-hover morris-default-style' 58281 }; 58282 58283 function Hover(options) { 58284 if (options == null) { 58285 options = {}; 58286 } 58287 this.options = $.extend({}, Morris.Hover.defaults, options); 58288 this.el = $("<div class='" + this.options["class"] + "'></div>"); 58289 this.el.hide(); 58290 this.options.parent.append(this.el); 58291 } 58292 58293 Hover.prototype.update = function(html, x, y) { 58294 if (!html) { 58295 return this.hide(); 58296 } else { 58297 this.html(html); 58298 this.show(); 58299 return this.moveTo(x, y); 58300 } 58301 }; 58302 58303 Hover.prototype.html = function(content) { 58304 return this.el.html(content); 58305 }; 58306 58307 Hover.prototype.moveTo = function(x, y) { 58308 var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top; 58309 parentWidth = this.options.parent.innerWidth(); 58310 parentHeight = this.options.parent.innerHeight(); 58311 hoverWidth = this.el.outerWidth(); 58312 hoverHeight = this.el.outerHeight(); 58313 left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth); 58314 if (y != null) { 58315 top = y - hoverHeight - 10; 58316 if (top < 0) { 58317 top = y + 10; 58318 if (top + hoverHeight > parentHeight) { 58319 top = parentHeight / 2 - hoverHeight / 2; 58320 } 58321 } 58322 } else { 58323 top = parentHeight / 2 - hoverHeight / 2; 58324 } 58325 return this.el.css({ 58326 left: left + "px", 58327 top: parseInt(top) + "px" 58328 }); 58329 }; 58330 58331 Hover.prototype.show = function() { 58332 return this.el.show(); 58333 }; 58334 58335 Hover.prototype.hide = function() { 58336 return this.el.hide(); 58337 }; 58338 58339 return Hover; 58340 58341 })(); 58342 58343 Morris.Line = (function(_super) { 58344 __extends(Line, _super); 58345 58346 function Line(options) { 58347 this.hilight = __bind(this.hilight, this); 58348 this.onHoverOut = __bind(this.onHoverOut, this); 58349 this.onHoverMove = __bind(this.onHoverMove, this); 58350 this.onGridClick = __bind(this.onGridClick, this); 58351 if (!(this instanceof Morris.Line)) { 58352 return new Morris.Line(options); 58353 } 58354 Line.__super__.constructor.call(this, options); 58355 } 58356 58357 Line.prototype.init = function() { 58358 if (this.options.hideHover !== 'always') { 58359 this.hover = new Morris.Hover({ 58360 parent: this.el 58361 }); 58362 this.on('hovermove', this.onHoverMove); 58363 this.on('hoverout', this.onHoverOut); 58364 return this.on('gridclick', this.onGridClick); 58365 } 58366 }; 58367 58368 Line.prototype.defaults = { 58369 lineWidth: 3, 58370 pointSize: 4, 58371 lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'], 58372 pointStrokeWidths: [1], 58373 pointStrokeColors: ['#ffffff'], 58374 pointFillColors: [], 58375 smooth: true, 58376 xLabels: 'auto', 58377 xLabelFormat: null, 58378 xLabelMargin: 24, 58379 hideHover: false 58380 }; 58381 58382 Line.prototype.calc = function() { 58383 this.calcPoints(); 58384 return this.generatePaths(); 58385 }; 58386 58387 Line.prototype.calcPoints = function() { 58388 var row, y, _i, _len, _ref, _results; 58389 _ref = this.data; 58390 _results = []; 58391 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 58392 row = _ref[_i]; 58393 row._x = this.transX(row.x); 58394 row._y = (function() { 58395 var _j, _len1, _ref1, _results1; 58396 _ref1 = row.y; 58397 _results1 = []; 58398 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 58399 y = _ref1[_j]; 58400 if (y != null) { 58401 _results1.push(this.transY(y)); 58402 } else { 58403 _results1.push(y); 58404 } 58405 } 58406 return _results1; 58407 }).call(this); 58408 _results.push(row._ymax = Math.min.apply(Math, [this.bottom].concat((function() { 58409 var _j, _len1, _ref1, _results1; 58410 _ref1 = row._y; 58411 _results1 = []; 58412 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 58413 y = _ref1[_j]; 58414 if (y != null) { 58415 _results1.push(y); 58416 } 58417 } 58418 return _results1; 58419 })()))); 58420 } 58421 return _results; 58422 }; 58423 58424 Line.prototype.hitTest = function(x) { 58425 var index, r, _i, _len, _ref; 58426 if (this.data.length === 0) { 58427 return null; 58428 } 58429 _ref = this.data.slice(1); 58430 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 58431 r = _ref[index]; 58432 if (x < (r._x + this.data[index]._x) / 2) { 58433 break; 58434 } 58435 } 58436 return index; 58437 }; 58438 58439 Line.prototype.onGridClick = function(x, y) { 58440 var index; 58441 index = this.hitTest(x); 58442 return this.fire('click', index, this.data[index].src, x, y); 58443 }; 58444 58445 Line.prototype.onHoverMove = function(x, y) { 58446 var index; 58447 index = this.hitTest(x); 58448 return this.displayHoverForRow(index); 58449 }; 58450 58451 Line.prototype.onHoverOut = function() { 58452 if (this.options.hideHover !== false) { 58453 return this.displayHoverForRow(null); 58454 } 58455 }; 58456 58457 Line.prototype.displayHoverForRow = function(index) { 58458 var _ref; 58459 if (index != null) { 58460 (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index)); 58461 return this.hilight(index); 58462 } else { 58463 this.hover.hide(); 58464 return this.hilight(); 58465 } 58466 }; 58467 58468 Line.prototype.hoverContentForRow = function(index) { 58469 var content, j, row, y, _i, _len, _ref; 58470 row = this.data[index]; 58471 content = "<div class='morris-hover-row-label'>" + row.label + "</div>"; 58472 _ref = row.y; 58473 for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) { 58474 y = _ref[j]; 58475 content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>"; 58476 } 58477 if (typeof this.options.hoverCallback === 'function') { 58478 content = this.options.hoverCallback(index, this.options, content, row.src
58478); 58479 } 58480 return [content, row._x, row._ymax]; 58481 }; 58482 58483 Line.prototype.generatePaths = function() { 58484 var coords, i, r, smooth; 58485 return this.paths = (function() { 58486 var _i, _ref, _ref1, _results; 58487 _results = []; 58488 for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { 58489 smooth = typeof this.options.smooth === "boolean" ? this.options.smooth : (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0); 58490 coords = (function() { 58491 var _j, _len, _ref2, _results1; 58492 _ref2 = this.data; 58493 _results1 = []; 58494 for (_j = 0, _len = _ref2.length; _j < _len; _j++) { 58495 r = _ref2[_j]; 58496 if (r._y[i] !== void 0) { 58497 _results1.push({ 58498 x: r._x, 58499 y: r._y[i] 58500 }); 58501 } 58502 } 58503 return _results1; 58504 }).call(this); 58505 if (coords.length > 1) { 58506 _results.push(Morris.Line.createPath(coords, smooth, this.bottom)); 58507 } else { 58508 _results.push(null); 58509 } 58510 } 58511 return _results; 58512 }).call(this); 58513 }; 58514 58515 Line.prototype.draw = function() { 58516 var _ref; 58517 if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') { 58518 this.drawXAxis(); 58519 } 58520 this.drawSeries(); 58521 if (this.options.hideHover === false) { 58522 return this.displayHoverForRow(this.data.length - 1); 58523 } 58524 }; 58525 58526 Line.prototype.drawXAxis = function() { 58527 var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results, 58528 _this = this; 58529 ypos = this.bottom + this.options.padding / 2; 58530 prevLabelMargin = null; 58531 prevAngleMargin = null; 58532 drawLabel = function(labelText, xpos) { 58533 var label, labelBox, margin, offset, textBox; 58534 label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText); 58535 textBox = label.getBBox(); 58536 label.transform("r" + (-_this.options.xLabelAngle)); 58537 labelBox = label.getBBox(); 58538 label.transform("t0," + (labelBox.height / 2) + "..."); 58539 if (_this.options.xLabelAngle !== 0) { 58540 offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0); 58541 label.transform("t" + offset + ",0..."); 58542 } 58543 labelBox = label.getBBox(); 58544 if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) { 58545 if (_this.options.xLabelAngle !== 0) { 58546 margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0); 58547 prevAngleMargin = labelBox.x - margin; 58548 } 58549 return prevLabelMargin = labelBox.x - _this.options.xLabelMargin; 58550 } else { 58551 return label.remove(); 58552 } 58553 }; 58554 if (this.options.parseTime) { 58555 if (this.data.length === 1 && this.options.xLabels === 'auto') { 58556 labels = [[this.data[0].label, this.data[0].x]]; 58557 } else { 58558 labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat); 58559 } 58560 } else { 58561 labels = (function() { 58562 var _i, _len, _ref, _results; 58563 _ref = this.data; 58564 _results = []; 58565 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 58566 row = _ref[_i]; 58567 _results.push([row.label, row.x]); 58568 } 58569 return _results; 58570 }).call(this); 58571 } 58572 labels.reverse(); 58573 _results = []; 58574 for (_i = 0, _len = labels.length; _i < _len; _i++) { 58575 l = labels[_i]; 58576 _results.push(drawLabel(l[0], l[1])); 58577 } 58578 return _results; 58579 }; 58580 58581 Line.prototype.drawSeries = function() { 58582 var i, _i, _j, _ref, _ref1, _results; 58583 this.seriesPoints = []; 58584 for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { 58585 this._drawLineFor(i); 58586 } 58587 _results = []; 58588 for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) { 58589 _results.push(this._drawPointFor(i)); 58590 } 58591 return _results; 58592 }; 58593 58594 Line.prototype._drawPointFor = function(index) { 58595 var circle, row, _i, _len, _ref, _results; 58596 this.seriesPoints[index] = []; 58597 _ref = this.data; 58598 _results = []; 58599 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 58600 row = _ref[_i]; 58601 circle = null; 58602 if (row._y[index] != null) { 58603 circle = this.drawLinePoint(row._x, row._y[index], this.colorFor(row, index, 'point'), index); 58604 } 58605 _results.push(this.seriesPoints[index].push(circle)); 58606 } 58607 return _results; 58608 }; 58609 58610 Line.prototype._drawLineFor = function(index) { 58611 var path; 58612 path = this.paths[index]; 58613 if (path !== null) { 58614 return this.drawLinePath(path, this.colorFor(null, index, 'line'), index); 58615 } 58616 }; 58617 58618 Line.createPath = function(coords, smooth, bottom) { 58619 var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len; 58620 path = ""; 58621 if (smooth) { 58622 grads = Morris.Line.gradients(coords); 58623 } 58624 prevCoord = { 58625 y: null 58626 };
58627 for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) { 58628 coord = coords[i]; 58629 if (coord.y != null) { 58630 if (prevCoord.y != null) { 58631 if (smooth) { 58632 g = grads[i]; 58633 lg = grads[i - 1]; 58634 ix = (coord.x - prevCoord.x) / 4; 58635 x1 = prevCoord.x + ix; 58636 y1 = Math.min(bottom, prevCoord.y + ix * lg); 58637 x2 = coord.x - ix; 58638 y2 = Math.min(bottom, coord.y - ix * g); 58639 path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y; 58640 } else { 58641 path += "L" + coord.x + "," + coord.y; 58642 } 58643 } else { 58644 if (!smooth || (grads[i] != null)) { 58645 path += "M" + coord.x + "," + coord.y; 58646 } 58647 } 58648 } 58649 prevCoord = coord; 58650 } 58651 return path; 58652 }; 58653 58654 Line.gradients = function(coords) { 58655 var coord, grad, i, nextCoord, prevCoord, _i, _len, _results; 58656 grad = function(a, b) { 58657 return (a.y - b.y) / (a.x - b.x); 58658 }; 58659 _results = []; 58660 for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) { 58661 coord = coords[i]; 58662 if (coord.y != null) { 58663 nextCoord = coords[i + 1] || { 58664 y: null 58665 }; 58666 prevCoord = coords[i - 1] || { 58667 y: null 58668 }; 58669 if ((prevCoord.y != null) && (nextCoord.y != null)) { 58670 _results.push(grad(prevCoord, nextCoord)); 58671 } else if (prevCoord.y != null) { 58672 _results.push(grad(prevCoord, coord)); 58673 } else if (nextCoord.y != null) { 58674 _results.push(grad(coord, nextCoord)); 58675 } else { 58676 _results.push(null); 58677 } 58678 } else { 58679 _results.push(null); 58680 } 58681 } 58682 return _results; 58683 }; 58684 58685 Line.prototype.hilight = function(index) { 58686 var i, _i, _j, _ref, _ref1; 58687 if (this.prevHilight !== null && this.prevHilight !== index) { 58688 for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) { 58689 if (this.seriesPoints[i][this.prevHilight]) { 58690 this.seriesPoints[i][this.prevHilight].animate(this.pointShrinkSeries(i)); 58691 } 58692 } 58693 } 58694 if (index !== null && this.prevHilight !== index) { 58695 for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) { 58696 if (this.seriesPoints[i][index]) { 58697 this.seriesPoints[i][index].animate(this.pointGrowSeries(i)); 58698 } 58699 } 58700 } 58701 return this.prevHilight = index; 58702 }; 58703 58704 Line.prototype.colorFor = function(row, sidx, type) { 58705 if (typeof this.options.lineColors === 'function') { 58706 return this.options.lineColors.call(this, row, sidx, type); 58707 } else if (type === 'point') { 58708 return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length]; 58709 } else { 58710 return this.options.lineColors[sidx % this.options.lineColors.length]; 58711 } 58712 }; 58713 58714 Line.prototype.drawXAxisLabel = function(xPos, yPos, text) { 58715 return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor); 58716 }; 58717 58718 Line.prototype.drawLinePath = function(path, lineColor, lineIndex) { 58719 return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.lineWidthForSeries(lineIndex)); 58720 }; 58721 58722 Line.prototype.drawLinePoint = function(xPos, yPos, pointColor, lineIndex) { 58723 return this.raphael.circle(xPos, yPos, this.pointSizeForSeries(lineIndex)).attr('fill', pointColor).attr('stroke-width', this.pointStrokeWidthForSeries(lineIndex)).attr('stroke', this.pointStrokeColorForSeries(lineIndex)); 58724 }; 58725 58726 Line.prototype.pointStrokeWidthForSeries = function(index) { 58727 return this.options.pointStrokeWidths[index % this.options.pointStrokeWidths.length]; 58728 }; 58729 58730 Line.prototype.pointStrokeColorForSeries = function(index) { 58731 return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length]; 58732 }; 58733 58734 Line.prototype.lineWidthForSeries = function(index) { 58735 if (this.options.lineWidth instanceof Array) { 58736 return this.options.lineWidth[index % this.options.lineWidth.length]; 58737 } else { 58738 return this.options.lineWidth; 58739 } 58740 }; 58741 58742 Line.prototype.pointSizeForSeries = function(index) { 58743 if (this.options.pointSize instanceof Array) { 58744 return this.options.pointSize[index % this.options.pointSize.length]; 58745 } else { 58746 return this.options.pointSize; 58747 } 58748 }; 58749 58750 Line.prototype.pointGrowSeries = function(index) { 58751 return Raphael.animation({ 58752 r: this.pointSizeForSeries(index) + 3 58753 }, 25, 'linear'); 58754 }; 58755 58756 Line.prototype.pointShrinkSeries = function(index) { 58757 return Raphael.animation({ 58758 r: this.pointSizeForSeries(index) 58759 }, 25, 'linear'); 58760 }; 58761 58762 return Line; 58763 58764 })(Morris.Grid); 58765 58766 Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) { 58767 var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref; 58768 ddensity = 200 * (dmax - dmin) / pxwidth; 58769 d0 = new Date(dmin); 58770 spec = Morris.LABEL_SPECS[specName]; 58771 if (spec === void 0) { 58772 _ref = Morris.AUTO_LABEL_ORDER; 58773 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 58774 name = _ref[_i]; 58775 s = Morris.LABEL_SPECS[name]; 58776 if (ddensity >= s.span) { 58777 spec = s; 58778 break; 58779 } 58780 } 58781 } 58782 if (spec === void 0) { 58783 spec = Morris.LABEL_SPECS["second"]; 58784 } 58785 if (xLabelFormat) { 58786 spec = $.extend({}, spec, { 58787 fmt: xLabelFormat 58788 }); 58789 } 58790 d = spec.start(d0); 58791 ret = []; 58792 while ((t = d.getTime()) <= dmax) { 58793 if (t >= dmin) {
58794 ret.push([spec.fmt(d), t]); 58795 } 58796 spec.incr(d); 58797 } 58798 return ret; 58799 }; 58800 58801 minutesSpecHelper = function(interval) { 58802 return { 58803 span: interval * 60 * 1000, 58804 start: function(d) { 58805 return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()); 58806 }, 58807 fmt: function(d) { 58808 return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())); 58809 }, 58810 incr: function(d) { 58811 return d.setUTCMinutes(d.getUTCMinutes() + interval); 58812 } 58813 }; 58814 }; 58815 58816 secondsSpecHelper = function(interval) { 58817 return { 58818 span: interval * 1000, 58819 start: function(d) { 58820 return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes()); 58821 }, 58822 fmt: function(d) { 58823 return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds())); 58824 }, 58825 incr: function(d) { 58826 return d.setUTCSeconds(d.getUTCSeconds() + interval); 58827 } 58828 }; 58829 }; 58830 58831 Morris.LABEL_SPECS = { 58832 "decade": { 58833 span: 172800000000, 58834 start: function(d) { 58835 return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1); 58836 }, 58837 fmt: function(d) { 58838 return "" + (d.getFullYear()); 58839 }, 58840 incr: function(d) { 58841 return d.setFullYear(d.getFullYear() + 10); 58842 } 58843 }, 58844 "year": { 58845 span: 17280000000, 58846 start: function(d) { 58847 return new Date(d.getFullYear(), 0, 1); 58848 }, 58849 fmt: function(d) { 58850 return "" + (d.getFullYear()); 58851 }, 58852 incr: function(d) { 58853 return d.setFullYear(d.getFullYear() + 1); 58854 } 58855 }, 58856 "month": { 58857 span: 2419200000, 58858 start: function(d) { 58859 return new Date(d.getFullYear(), d.getMonth(), 1); 58860 }, 58861 fmt: function(d) { 58862 return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)); 58863 }, 58864 incr: function(d) { 58865 return d.setMonth(d.getMonth() + 1); 58866 } 58867 }, 58868 "week": { 58869 span: 604800000, 58870 start: function(d) { 58871 return new Date(d.getFullYear(), d.getMonth(), d.getDate()); 58872 }, 58873 fmt: function(d) { 58874 return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate())); 58875 }, 58876 incr: function(d) { 58877 return d.setDate(d.getDate() + 7); 58878 } 58879 }, 58880 "day": { 58881 span: 86400000, 58882 start: function(d) { 58883 return new Date(d.getFullYear(), d.getMonth(), d.getDate()); 58884 }, 58885 fmt: function(d) { 58886 return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate())); 58887 }, 58888 incr: function(d) { 58889 return d.setDate(d.getDate() + 1); 58890 } 58891 }, 58892 "hour": minutesSpecHelper(60), 58893 "30min": minutesSpecHelper(30), 58894 "15min": minutesSpecHelper(15), 58895 "10min": minutesSpecHelper(10), 58896 "5min": minutesSpecHelper(5), 58897 "minute": minutesSpecHelper(1), 58898 "30sec": secondsSpecHelper(30), 58899 "15sec": secondsSpecHelper(15), 58900 "10sec": secondsSpecHelper(10), 58901 "5sec": secondsSpecHelper(5), 58902 "second": secondsSpecHelper(1) 58903 }; 58904 58905 Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "week", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"]; 58906 58907 Morris.Area = (function(_super) { 58908 var areaDefaults; 58909 58910 __extends(Area, _super); 58911 58912 areaDefaults = { 58913 fillOpacity: 'auto', 58914 behaveLikeLine: false 58915 }; 58916 58917 function Area(options) { 58918 var areaOptions; 58919 if (!(this instanceof Morris.Area)) { 58920 return new Morris.Area(options); 58921 } 58922 areaOptions = $.extend({}, areaDefaults, options); 58923 this.cumulative = !areaOptions.behaveLikeLine; 58924 if (areaOptions.fillOpacity === 'auto') { 58925 areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1; 58926 } 58927 Area.__super__.constructor.call(this, areaOptions); 58928 } 58929 58930 Area.prototype.calcPoints = function() { 58931 var row, total, y, _i, _len, _ref, _results; 58932 _ref = this.data; 58933 _results = []; 58934 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 58935 row = _ref[_i]; 58936 row._x = this.transX(row.x); 58937 total = 0; 58938 row._y = (function() { 58939 var _j, _len1, _ref1, _results1; 58940 _ref1 = row.y; 58941 _results1 = []; 58942 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 58943 y = _ref1[_j]; 58944 if (this.options.behaveLikeLine) { 58945 _results1.push(this.transY(y)); 58946 } else { 58947 total += y || 0; 58948 _results1.push(this.transY(total)); 58949 } 58950 } 58951 return _results1; 58952 }).call(this); 58953 _results.push(row._ymax = Math.max.apply(Math, row._y)); 58954 } 58955 return _results; 58956 }; 58957 58958 Area.prototype.drawSeries = function() { 58959 var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2; 58960 this.seriesPoints = []; 58961 if (this.options.behaveLikeLine) { 58962 range = (function() { 58963 _results = []; 58964 for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } 58965 return _results; 58966 }).apply(this); 58967 } else { 58968 range = (function() { 58969 _results1 = []; 58970 for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); } 58971 return _results1; 58972 }).apply(this); 58973 } 58974 _results2 = []; 58975 for (_k = 0, _len = range.length; _k < _len; _k++) { 58976 i = range[_k]; 58977 this._drawFillFor(i); 58978 this._drawLineFor(i); 58979 _results2.push(this._drawPointFor(i)); 58980 } 58981 return _results2; 58982 }; 58983 58984 Area.prototype._drawFillFor = function(index) { 58985 var path; 58986 path = this.paths[index]; 58987 if (path !== null) { 58988 path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z"); 58989 return this.drawFilledPath(path, this.fillForSeries(index)); 58990 } 58991 }; 58992 58993 Area.prototype.fillForSeries = function(i) { 58994 var color; 58995 color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line')); 58996 return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25)); 58997 }; 58998 58999 Area.prototype.drawFilledPath = function(path, fill) { 59000 return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke', 'none'); 59001 }; 59002 59003 return Area; 59004 59005 })(Morris.Line); 59006 59007 Morris.Bar = (function(_super) { 59008 __extends(Bar, _super); 59009 59010 function Bar(options) { 59011 this.onHoverOut = __bind(this.onHoverOut, this); 59012 this.onHoverMove = __bind(this.onHoverMove, this); 59013 this.onGridClick = __bind(this.onGridClick, this); 59014 if (!(this instanceof Morris.Bar)) { 59015 return new Morris.Bar(options); 59016 } 59017 Bar.__super__.constructor.call(this, $.extend({}, options, { 59018 parseTime: false 59019 })); 59020 } 59021 59022 Bar.prototype.init = function() { 59023 this.cumulative = this.options.stacked; 59024 if (this.options.hideHover !== 'always') { 59025 this.hover = new Morris.Hover({ 59026 parent: this.el 59027 }); 59028 this.on('hovermove', this.onHoverMove); 59029 this.on('hoverout', this.onHoverOut); 59030 return this.on('gridclick', this.onGridClick); 59031 } 59032 }; 59033 59034 Bar.prototype.defaults = { 59035 barSizeRatio: 0.75, 59036 barGap: 3, 59037 barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'], 59038 barOpacity: 1.0, 59039 barRadius: [0, 0, 0, 0], 59040 xLabelMargin: 50 59041 }; 59042 59043 Bar.prototype.calc = function() { 59044 var _ref; 59045 this.calcBars(); 59046 if (this.options.hideHover === false) { 59047 return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1)); 59048 } 59049 }; 59050 59051 Bar.prototype.calcBars = function() { 59052 var idx, row, y, _i, _len, _ref, _results; 59053 _ref = this.data; 59054 _results = []; 59055 for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { 59056 row = _ref[idx]; 59057 row._x = this.left + this.width * (idx + 0.5) / this.data.length; 59058 _results.push(row._y = (function() { 59059 var _j, _len1, _ref1, _results1; 59060 _ref1 = row.y; 59061 _results1 = []; 59062 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { 59063 y = _ref1[_j]; 59064 if (y != null) { 59065 _results1.push(this.transY(y)); 59066 } else { 59067 _results1.push(null); 59068 } 59069 } 59070 return _results1; 59071 }).call(this)); 59072 } 59073 return _results; 59074 }; 59075 59076 Bar.prototype.draw = function() { 59077 var _ref; 59078 if ((_ref = this.options.axes) === true || _ref === 'both' || _ref === 'x') { 59079 this.drawXAxis(); 59080 } 59081 return this.drawSeries(); 59082 }; 59083 59084 Bar.prototype.drawXAxis = function() { 59085 var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results; 59086 ypos = this.bottom + (this.options.xAxisLabelTopPadding || this.options.padding / 2); 59087 prevLabelMargin = null; 59088 prevAngleMargin = null; 59089 _results = []; 59090 for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { 59091 row = this.data[this.data.length - 1 - i]; 59092 label = this.drawXAxisLabel(row._x, ypos, row.label); 59093 textBox = label.getBBox(); 59094 label.transform("r" + (-this.options.xLabelAngle)); 59095 labelBox = label.getBBox(); 59096 label.transform("t0," + (labelBox.height / 2) + "..."); 59097 if (this.options.xLabelAngle !== 0) { 59098 offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0); 59099 label.transform("t" + offset + ",0..."); 59100 } 59101 if (((prevLabelMargin == null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) { 59102 if (this.options.xLabelAngle !== 0) { 59103 margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0); 59104 prevAngleMargin = labelBox.x - margin; 59105 } 59106 _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin); 59107 } else { 59108 _results.push(label.remove()); 59109 } 59110 } 59111 return _results; 59112 }; 59113 59114 Bar.prototype.drawSeries = function() { 59115 var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, space
59115Left, top, ypos, zeroPos; 59116 groupWidth = this.width / this.options.data.length; 59117 numBars = this.options.stacked ? 1 : this.options.ykeys.length; 59118 barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars; 59119 if (this.options.barSize) { 59120 barWidth = Math.min(barWidth, this.options.barSize); 59121 } 59122 spaceLeft = groupWidth - barWidth * numBars - this.options.barGap * (numBars - 1); 59123 leftPadding = spaceLeft / 2; 59124 zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null; 59125 return this.bars = (function() { 59126 var _i, _len, _ref, _results; 59127 _ref = this.data; 59128 _results = []; 59129 for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { 59130 row = _ref[idx]; 59131 lastTop = 0; 59132 _results.push((function() { 59133 var _j, _len1, _ref1, _results1; 59134 _ref1 = row._y; 59135 _results1 = []; 59136 for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) { 59137 ypos = _ref1[sidx]; 59138 if (ypos !== null) { 59139 if (zeroPos) { 59140 top = Math.min(ypos, zeroPos); 59141 bottom = Math.max(ypos, zeroPos); 59142 } else { 59143 top = ypos; 59144 bottom = this.bottom; 59145 } 59146 left = this.left + idx * groupWidth + leftPadding; 59147 if (!this.options.stacked) { 59148 left += sidx * (barWidth + this.options.barGap); 59149 } 59150 size = bottom - top; 59151 if (this.options.verticalGridCondition && this.options.verticalGridCondition(row.x)) { 59152 this.drawBar(this.left + idx * groupWidth, this.top, groupWidth, Math.abs(this.top - this.bottom), this.options.verticalGridColor, this.options.verticalGridOpacity, this.options.barRadius); 59153 } 59154 if (this.options.stacked) { 59155 top -= lastTop; 59156 } 59157 this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius); 59158 _results1.push(lastTop += size); 59159 } else { 59160 _results1.push(null); 59161 } 59162 } 59163 return _results1; 59164 }).call(this)); 59165 } 59166 return _results; 59167 }).call(this); 59168 }; 59169 59170 Bar.prototype.colorFor = function(row, sidx, type) { 59171 var r, s; 59172 if (typeof this.options.barColors === 'function') { 59173 r = { 59174 x: row.x, 59175 y: row.y[sidx], 59176 label: row.label 59177 }; 59178 s = { 59179 index: sidx, 59180 key: this.options.ykeys[sidx], 59181 label: this.options.labels[sidx] 59182 }; 59183 return this.options.barColors.call(this, r, s, type); 59184 } else { 59185 return this.options.barColors[sidx % this.options.barColors.length]; 59186 } 59187 }; 59188 59189 Bar.prototype.hitTest = function(x) { 59190 if (this.data.length === 0) { 59191 return null; 59192 } 59193 x = Math.max(Math.min(x, this.right), this.left); 59194 return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length))); 59195 }; 59196 59197 Bar.prototype.onGridClick = function(x, y) { 59198 var index; 59199 index = this.hitTest(x); 59200 return this.fire('click', index, this.data[index].src, x, y); 59201 }; 59202 59203 Bar.prototype.onHoverMove = function(x, y) { 59204 var index, _ref; 59205 index = this.hitTest(x); 59206 return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index)); 59207 }; 59208 59209 Bar.prototype.onHoverOut = function() { 59210 if (this.options.hideHover !== false) { 59211 return this.hover.hide(); 59212 } 59213 }; 59214 59215 Bar.prototype.hoverContentForRow = function(index) { 59216 var content, j, row, x, y, _i, _len, _ref; 59217 row = this.data[index]; 59218 content = "<div class='morris-hover-row-label'>" + row.label + "</div>"; 59219 _ref = row.y; 59220 for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) { 59221 y = _ref[j]; 59222 content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>"; 59223 } 59224 if (typeof this.options.hoverCallback === 'function') { 59225 content = this.options.hoverCallback(index, this.options, content, row.src
59225); 59226 } 59227 x = this.left + (index + 0.5) * this.width / this.data.length; 59228 return [content, x]; 59229 }; 59230 59231 Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) { 59232 var label; 59233 return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor); 59234 }; 59235 59236 Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor, opacity, radiusArray) { 59237 var maxRadius, path; 59238 maxRadius = Math.max.apply(Math, radiusArray); 59239 if (maxRadius === 0 || maxRadius > height) { 59240 path = this.raphael.rect(xPos, yPos, width, height); 59241 } else { 59242 path = this.raphael.path(this.roundedRect(xPos, yPos, width, height, radiusArray)); 59243 } 59244 return path.attr('fill', barColor).attr('fill-opacity', opacity).attr('stroke', 'none'); 59245 }; 59246 59247 Bar.prototype.roundedRect = function(x, y, w, h, r) { 59248 if (r == null) { 59249 r = [0, 0, 0, 0]; 59250 } 59251 return ["M", x, r[0] + y, "Q", x, y, x + r[0], y, "L", x + w - r[1], y, "Q", x + w, y, x + w, y + r[1], "L", x + w, y + h - r[2], "Q", x + w, y + h, x + w - r[2], y + h, "L", x + r[3], y + h, "Q", x, y + h, x, y + h - r[3], "Z"]; 59252 }; 59253 59254 return Bar; 59255 59256 })(Morris.Grid); 59257 59258 Morris.Donut = (function(_super) { 59259 __extends(Donut, _super); 59260 59261 Donut.prototype.defaults = { 59262 colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'], 59263 backgroundColor: '#FFFFFF', 59264 labelColor: '#000000', 59265 formatter: Morris.commas, 59266 resize: false 59267 }; 59268 59269 function Donut(options) { 59270 this.resizeHandler = __bind(this.resizeHandler, this); 59271 this.select = __bind(this.select, this); 59272 this.click = __bind(this.click, this); 59273 var _this = this; 59274 if (!(this instanceof Morris.Donut)) { 59275 return new Morris.Donut(options); 59276 } 59277 this.options = $.extend({}, this.defaults, options); 59278 if (typeof options.element === 'string') { 59279 this.el = $(document.getElementById(options.element)); 59280 } else { 59281 this.el = $(options.element); 59282 } 59283 if (this.el === null || this.el.length === 0) { 59284 throw new Error("Graph placeholder not found."); 59285 } 59286 if (options.data === void 0 || options.data.length === 0) { 59287 return; 59288 } 59289 this.raphael = new Raphael(this.el[0]); 59290 if (this.options.resize) { 59291 $(window).bind('resize', function(evt) { 59292 if (_this.timeoutId != null) { 59293 window.clearTimeout(_this.timeoutId); 59294 } 59295 return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100); 59296 }); 59297 } 59298 this.setData(options.data); 59299 } 59300 59301 Donut.prototype.redraw = function() { 59302 var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; 59303 this.raphael.clear(); 59304 cx = this.el.width() / 2; 59305 cy = this.el.height() / 2; 59306 w = (Math.min(cx, cy) - 10) / 3; 59307 total = 0; 59308 _ref = this.values; 59309 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 59310 value = _ref[_i]; 59311 total += value; 59312 } 59313 min = 5 / (2 * w); 59314 C = 1.9999 * Math.PI - min * this.data.length; 59315 last = 0; 59316 idx = 0; 59317 this.segments = []; 59318 _ref1 = this.values; 59319 for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) { 59320 value = _ref1[i]; 59321 next = last + min + C * (value / total); 59322 seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.data[i].color || this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael); 59323 seg.render(); 59324 this.segments.push(seg); 59325 seg.on('hover', this.select); 59326 seg.on('click', this.click); 59327 last = next; 59328 idx += 1; 59329 } 59330 this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800); 59331 this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14); 59332 max_value = Math.max.apply(Math, this.values); 59333 idx = 0; 59334 _ref2 = this.values; 59335 _results = []; 59336 for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { 59337 value = _ref2[_k]; 59338 if (value === max_value) { 59339 this.select(idx); 59340 break; 59341 } 59342 _results.push(idx += 1); 59343 } 59344 return _results; 59345 }; 59346 59347 Donut.prototype.setData = function(data) { 59348 var row; 59349 this.data = data; 59350 this.values = (function() { 59351 var _i, _len, _ref, _results; 59352 _ref = this.data; 59353 _results = []; 59354 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 59355 row = _ref[_i]; 59356 _results.push(parseFloat(row.value)); 59357 } 59358 return _results; 59359 }).call(this); 59360 return this.redraw(); 59361 }; 59362 59363 Donut.prototype.click = function(idx) { 59364 return this.fire('click', idx, this.data[idx]); 59365 }; 59366 59367 Donut.prototype.select = function(idx) { 59368 var row, s, segment, _i, _len, _ref; 59369 _ref = this.segments; 59370 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 59371 s = _ref[_i]; 59372 s.deselect(); 59373 } 59374 segment = this.segments[idx]; 59375 segment.select(); 59376 row = this.data[idx]; 59377 return this.setLabels(row.label, this.options.formatter(row.value, row)); 59378 }; 59379 59380 Donut.prototype.setLabels = function(label1, label2) { 59381 var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale; 59382 inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3; 59383 maxWidth = 1.8 * inner; 59384 maxHeightTop = inner / 2; 59385 maxHeightBottom = inner / 3; 59386 this.text1.attr({ 59387 text: label1, 59388 transform: '' 59389 }); 59390 text1bbox = this.text1.getBBox(); 59391 text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height); 59392 this.text1.attr({ 59393 transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height) 59394 }); 59395 this.text2.attr({ 59396 text: label2, 59397 transform: '' 59398 }); 59399 text2bbox = this.text2.getBBox(); 59400 text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height); 59401 return this.text2.attr({ 59402 transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y 59403 }); 59404 }; 59405 59406 Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) { 59407 var text; 59408 text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color); 59409 if (fontWeight != null) { 59410 text.attr('font-weight', fontWeight); 59411 } 59412 return text; 59413 }; 59414 59415 Donut.prototype.resizeHandler = function() { 59416 this.timeoutId = null; 59417 this.raphael.setSize(this.el.width(), this.el.height()); 59418 return this.redraw(); 59419 }; 59420 59421 return Donut; 59422 59423 })(Morris.EventEmitter); 59424 59425 Morris.DonutSegment = (function(_super) { 59426 __extends(DonutSegment, _super); 59427 59428 function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) { 59429 this.cx = cx; 59430 this.cy = cy; 59431 this.inner = inner; 59432 this.outer = outer; 59433 this.color = color; 59434 this.backgroundColor = backgroundColor; 59435 this.index = index; 59436 this.raphael = raphael; 59437 this.deselect = __bind(this.deselect, this); 59438 this.select = __bind(this.select, this); 59439 this.sin_p0 = Math.sin(p0); 59440 this.cos_p0 = Math.cos(p0); 59441 this.sin_p1 = Math.sin(p1); 59442 this.cos_p1 = Math.cos(p1); 59443 this.is_long = (p1 - p0) > Math.PI ? 1 : 0; 59444 this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5); 59445 this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer); 59446 this.hilight = this.calcArc(this.inner); 59447 } 59448 59449 DonutSegment.prototype.calcArcPoints = function(r) { 59450 return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1]; 59451 }; 59452 59453 DonutSegment.prototype.calcSegment = function(r1, r2) { 59454 var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1; 59455 _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1
59455= _ref[2], iy1 = _ref[3]; 59456 _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3]; 59457 return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z"; 59458 }; 59459 59460 DonutSegment.prototype.calcArc = function(r) { 59461 var ix0, ix1, iy0, iy1, _ref; 59462 _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; 59463 return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1); 59464 }; 59465 59466 DonutSegment.prototype.render = function() { 59467 var _this = this; 59468 this.arc = this.drawDonutArc(this.hilight, this.color); 59469 return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() { 59470 return _this.fire('hover', _this.index); 59471 }, function() { 59472 return _this.fire('click', _this.index); 59473 }); 59474 }; 59475 59476 DonutSegment.prototype.drawDonutArc = function(path, color) { 59477 return this.raphael.path(path).attr({ 59478 stroke: color, 59479 'stroke-width': 2, 59480 opacity: 0 59481 }); 59482 }; 59483 59484 DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) { 59485 return this.raphael.path(path).attr({ 59486 fill: fillColor, 59487 stroke: strokeColor, 59488 'stroke-width': 3 59489 }).hover(hoverFunction).click(clickFunction); 59490 }; 59491 59492 DonutSegment.prototype.select = function() { 59493 if (!this.selected) { 59494 this.seg.animate({ 59495 path: this.selectedPath 59496 }, 150, '<>'); 59497 this.arc.animate({ 59498 opacity: 1 59499 }, 150, '<>'); 59500 return this.selected = true; 59501 } 59502 }; 59503 59504 DonutSegment.prototype.deselect = function() { 59505 if (this.selected) { 59506 this.seg.animate({ 59507 path: this.path 59508 }, 150, '<>'); 59509 this.arc.animate({ 59510 opacity: 0 59511 }, 150, '<>'); 59512 return this.selected = false; 59513 } 59514 }; 59515 59516 return DonutSegment; 59517 59518 })(Morris.EventEmitter); 59519 59520}).call(this); 59521 59522/*! 59523 * Chart.js v2.8.0 59524 * https://www.chartjs.org 59525 * (c) 2019 Chart.js Contributors 59526 * Released under the MIT License 59527 */ 59528(function (global, factory) { 59529typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 59530typeof define === 'function' && define.amd ? define(factory) : 59531(global.Chart = factory()); 59532}(this, (function () { 'use strict'; 59533 59534/* MIT license */ 59535 59536var conversions = { 59537 rgb2hsl: rgb2hsl, 59538 rgb2hsv: rgb2hsv, 59539 rgb2hwb: rgb2hwb, 59540 rgb2cmyk: rgb2cmyk, 59541 rgb2keyword: rgb2keyword, 59542 rgb2xyz: rgb2xyz, 59543 rgb2lab: rgb2lab, 59544 rgb2lch: rgb2lch, 59545 59546 hsl2rgb: hsl2rgb, 59547 hsl2hsv: hsl2hsv, 59548 hsl2hwb: hsl2hwb, 59549 hsl2cmyk: hsl2cmyk, 59550 hsl2keyword: hsl2keyword, 59551 59552 hsv2rgb: hsv2rgb, 59553 hsv2hsl: hsv2hsl, 59554 hsv2hwb: hsv2hwb, 59555 hsv2cmyk: hsv2cmyk, 59556 hsv2keyword: hsv2keyword, 59557 59558 hwb2rgb: hwb2rgb, 59559 hwb2hsl: hwb2hsl, 59560 hwb2hsv: hwb2hsv, 59561 hwb2cmyk: hwb2cmyk, 59562 hwb2keyword: hwb2keyword, 59563 59564 cmyk2rgb: cmyk2rgb, 59565 cmyk2hsl: cmyk2hsl, 59566 cmyk2hsv: cmyk2hsv, 59567 cmyk2hwb: cmyk2hwb, 59568 cmyk2keyword: cmyk2keyword, 59569 59570 keyword2rgb: keyword2rgb, 59571 keyword2hsl: keyword2hsl, 59572 keyword2hsv: keyword2hsv, 59573 keyword2hwb: keyword2hwb, 59574 keyword2cmyk: keyword2cmyk, 59575 keyword2lab: keyword2lab, 59576 keyword2xyz: keyword2xyz, 59577 59578 xyz2rgb: xyz2rgb, 59579 xyz2lab: xyz2lab, 59580 xyz2lch: xyz2lch, 59581 59582 lab2xyz: lab2xyz, 59583 lab2rgb: lab2rgb, 59584 lab2lch: lab2lch, 59585 59586 lch2lab: lch2lab, 59587 lch2xyz: lch2xyz, 59588 lch2rgb: lch2rgb 59589}; 59590 59591 59592function rgb2hsl(rgb) { 59593 var r = rgb[0]/255, 59594 g = rgb[1]/255, 59595 b = rgb[2]/255, 59596 min = Math.min(r, g, b), 59597 max = Math.max(r, g, b), 59598 delta = max - min, 59599 h, s, l; 59600 59601 if (max == min) 59602 h = 0; 59603 else if (r == max) 59604 h = (g - b) / delta; 59605 else if (g == max) 59606 h = 2 + (b - r) / delta; 59607 else if (b == max) 59608 h = 4 + (r - g)/ delta; 59609 59610 h = Math.min(h * 60, 360); 59611 59612 if (h < 0) 59613 h += 360; 59614 59615 l = (min + max) / 2; 59616 59617 if (max == min) 59618 s = 0; 59619 else if (l <= 0.5) 59620 s = delta / (max + min); 59621 else 59622 s = delta / (2 - max - min); 59623 59624 return [h, s * 100, l * 100]; 59625} 59626 59627function rgb2hsv(rgb) { 59628 var r = rgb[0], 59629 g = rgb[1], 59630 b = rgb[2], 59631 min = Math.min(r, g, b), 59632 max = Math.max(r, g, b), 59633 delta = max - min, 59634 h, s, v; 59635 59636 if (max == 0) 59637 s = 0; 59638 else 59639 s = (delta/max * 1000)/10; 59640 59641 if (max == min) 59642 h = 0; 59643 else if (r == max) 59644 h = (g - b) / delta; 59645 else if (g == max) 59646 h = 2 + (b - r) / delta; 59647 else if (b == max) 59648 h = 4 + (r - g) / delta; 59649 59650 h = Math.min(h * 60, 360); 59651 59652 if (h < 0) 59653 h += 360; 59654 59655 v = ((max / 255) * 1000) / 10; 59656 59657 return [h, s, v]; 59658} 59659 59660function rgb2hwb(rgb) { 59661 var r = rgb[0], 59662 g = rgb[1], 59663 b = rgb[2], 59664 h = rgb2hsl(rgb)[0], 59665 w = 1/255 * Math.min(r, Math.min(g, b)), 59666 b = 1 - 1/255 * Math.max(r, Math.max(g, b)); 59667 59668 return [h, w * 100, b * 100]; 59669} 59670 59671function rgb2cmyk(rgb) {
59672 var r = rgb[0] / 255, 59673 g = rgb[1] / 255, 59674 b = rgb[2] / 255, 59675 c, m, y, k; 59676 59677 k = Math.min(1 - r, 1 - g, 1 - b); 59678 c = (1 - r - k) / (1 - k) || 0; 59679 m = (1 - g - k) / (1 - k) || 0; 59680 y = (1 - b - k) / (1 - k) || 0; 59681 return [c * 100, m * 100, y * 100, k * 100]; 59682} 59683 59684function rgb2keyword(rgb) { 59685 return reverseKeywords[JSON.stringify(rgb)]; 59686} 59687 59688function rgb2xyz(rgb) { 59689 var r = rgb[0] / 255, 59690 g = rgb[1] / 255, 59691 b = rgb[2] / 255; 59692 59693 // assume sRGB 59694 r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); 59695 g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); 59696 b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); 59697 59698 var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); 59699 var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); 59700 var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); 59701 59702 return [x * 100, y *100, z * 100]; 59703} 59704 59705function rgb2lab(rgb) { 59706 var xyz = rgb2xyz(rgb), 59707 x = xyz[0], 59708 y = xyz[1], 59709 z = xyz[2], 59710 l, a, b; 59711 59712 x /= 95.047; 59713 y /= 100; 59714 z /= 108.883; 59715 59716 x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); 59717 y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); 59718 z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); 59719 59720 l = (116 * y) - 16; 59721 a = 500 * (x - y); 59722 b = 200 * (y - z); 59723 59724 return [l, a, b]; 59725} 59726 59727function rgb2lch(args) { 59728 return lab2lch(rgb2lab(args)); 59729} 59730 59731function hsl2rgb(hsl) { 59732 var h = hsl[0] / 360, 59733 s = hsl[1] / 100, 59734 l = hsl[2] / 100, 59735 t1, t2, t3, rgb, val; 59736 59737 if (s == 0) { 59738 val = l * 255; 59739 return [val, val, val]; 59740 } 59741 59742 if (l < 0.5) 59743 t2 = l * (1 + s); 59744 else 59745 t2 = l + s - l * s; 59746 t1 = 2 * l - t2; 59747 59748 rgb = [0, 0, 0]; 59749 for (var i = 0; i < 3; i++) { 59750 t3 = h + 1 / 3 * - (i - 1); 59751 t3 < 0 && t3++; 59752 t3 > 1 && t3--; 59753 59754 if (6 * t3 < 1) 59755 val = t1 + (t2 - t1) * 6 * t3; 59756 else if (2 * t3 < 1) 59757 val = t2; 59758 else if (3 * t3 < 2) 59759 val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; 59760 else 59761 val = t1; 59762 59763 rgb[i] = val * 255; 59764 } 59765 59766 return rgb; 59767} 59768 59769function hsl2hsv(hsl) { 59770 var h = hsl[0], 59771 s = hsl[1] / 100, 59772 l = hsl[2] / 100, 59773 sv, v; 59774 59775 if(l === 0) { 59776 // no need to do calc on black 59777 // also avoids divide by 0 error 59778 return [0, 0, 0]; 59779 } 59780 59781 l *= 2; 59782 s *= (l <= 1) ? l : 2 - l; 59783 v = (l + s) / 2; 59784 sv = (2 * s) / (l + s); 59785 return [h, sv * 100, v * 100]; 59786} 59787 59788function hsl2hwb(args) { 59789 return rgb2hwb(hsl2rgb(args)); 59790} 59791 59792function hsl2cmyk(args) { 59793 return rgb2cmyk(hsl2rgb(args)); 59794} 59795 59796function hsl2keyword(args) { 59797 return rgb2keyword(hsl2rgb(args)); 59798} 59799 59800 59801function hsv2rgb(hsv) { 59802 var h = hsv[0] / 60, 59803 s = hsv[1] / 100, 59804 v = hsv[2] / 100, 59805 hi = Math.floor(h) % 6; 59806 59807 var f = h - Math.floor(h), 59808 p = 255 * v * (1 - s), 59809 q = 255 * v * (1 - (s * f)), 59810 t = 255 * v * (1 - (s * (1 - f))), 59811 v = 255 * v; 59812 59813 switch(hi) { 59814 case 0: 59815 return [v, t, p]; 59816 case 1: 59817 return [q, v, p]; 59818 case 2: 59819 return [p, v, t]; 59820 case 3: 59821 return [p, q, v]; 59822 case 4: 59823 return [t, p, v]; 59824 case 5: 59825 return [v, p, q]; 59826 } 59827} 59828 59829function hsv2hsl(hsv) { 59830 var h = hsv[0], 59831 s = hsv[1] / 100, 59832 v = hsv[2] / 100, 59833 sl, l; 59834 59835 l = (2 - s) * v; 59836 sl = s * v; 59837 sl /= (l <= 1) ? l : 2 - l; 59838 sl = sl || 0; 59839 l /= 2; 59840 return [h, sl * 100, l * 100]; 59841} 59842 59843function hsv2hwb(args) { 59844 return rgb2hwb(hsv2rgb(args)) 59845} 59846 59847function hsv2cmyk(args) { 59848 return rgb2cmyk(hsv2rgb(args)); 59849} 59850 59851function hsv2keyword(args) { 59852 return rgb2keyword(hsv2rgb(args)); 59853} 59854 59855// http://dev.w3.org/csswg/css-color/#hwb-to-rgb 59856function hwb2rgb(hwb) { 59857 var h = hwb[0] / 360, 59858 wh = hwb[1] / 100, 59859 bl = hwb[2] / 100, 59860 ratio = wh + bl, 59861 i, v, f, n; 59862 59863 // wh + bl cant be > 1 59864 if (ratio > 1) { 59865 wh /= ratio; 59866 bl /= ratio; 59867 } 59868 59869 i = Math.floor(6 * h); 59870 v = 1 - bl; 59871 f = 6 * h - i; 59872 if ((i & 0x01) != 0) { 59873 f = 1 - f; 59874 } 59875 n = wh + f * (v - wh); // linear interpolation 59876 59877 switch (i) { 59878 default: 59879 case 6: 59880 case 0: r = v; g = n; b = wh; break; 59881 case 1: r = n; g = v; b = wh; break; 59882 case 2: r = wh; g = v; b = n; break; 59883 case 3: r = wh; g = n; b = v; break; 59884 case 4: r = n; g = wh; b = v; break; 59885 case 5: r = v; g = wh; b = n; break; 59886 } 59887 59888 return [r * 255, g * 255, b * 255]; 59889} 59890 59891function hwb2hsl(args) { 59892 return rgb2hsl(hwb2rgb(args)); 59893} 59894 59895function hwb2hsv(args) { 59896 return rgb2hsv(hwb2rgb(args)); 59897} 59898 59899function hwb2cmyk(args) { 59900 return rgb2cmyk(hwb2rgb(args)); 59901} 59902 59903function hwb2keyword(args) { 59904 return rgb2keyword(hwb2rgb(args)); 59905} 59906 59907function cmyk2rgb(cmyk) { 59908 var c = cmyk[0] / 100, 59909 m = cmyk[1] / 100, 59910 y = cmyk[2] / 100, 59911 k = cmyk[3] / 100, 59912 r, g, b; 59913 59914 r = 1 - Math.min(1, c * (1 - k) + k); 59915 g = 1 - Math.min(1, m * (1 - k) + k); 59916 b = 1 - Math.min(1, y * (1 - k) + k); 59917 return [r * 255, g * 255, b * 255]; 59918} 59919 59920function cmyk2hsl(args) { 59921 return rgb2hsl(cmyk2rgb(args)); 59922} 59923 59924function cmyk2hsv(args) { 59925 return rgb2hsv(cmyk2rgb(args)); 59926} 59927 59928function cmyk2hwb(args) { 59929 return rgb2hwb(cmyk2rgb(args)); 59930} 59931 59932function cmyk2keyword(args) { 59933 return rgb2keyword(cmyk2rgb(args)); 59934} 59935 59936 59937function xyz2rgb(xyz) { 59938 var x = xyz[0] / 100, 59939 y = xyz[1] / 100, 59940 z = xyz[2] / 100, 59941 r, g, b; 59942 59943 r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); 59944 g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); 59945 b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); 59946 59947 // assume sRGB 59948 r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) 59949 : r = (r * 12.92); 59950 59951 g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) 59952 : g = (g * 12.92); 59953 59954 b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) 59955 : b = (b * 12.92); 59956 59957 r = Math.min(Math.max(0, r), 1); 59958 g = Math.min(Math.max(0, g), 1); 59959 b = Math.min(Math.max(0, b), 1); 59960 59961 return [r * 255, g * 255, b * 255]; 59962} 59963 59964function xyz2lab(xyz) { 59965 var x = xyz[0], 59966 y = xyz[1], 59967 z = xyz[2], 59968 l, a, b; 59969 59970 x /= 95.047; 59971 y /= 100; 59972 z /= 108.883; 59973 59974 x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); 59975 y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); 59976 z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); 59977 59978 l = (116 * y) - 16; 59979 a = 500 * (x - y); 59980 b = 200 * (y - z); 59981 59982 return [l, a, b]; 59983} 59984 59985function xyz2lch(args) { 59986 return lab2lch(xyz2lab(args)); 59987} 59988 59989function lab2xyz(lab) { 59990 var l = lab[0], 59991 a = lab[1], 59992 b = lab[2], 59993 x, y, z, y2; 59994 59995 if (l <= 8) { 59996 y = (l * 100) / 903.3; 59997 y2 = (7.787 * (y / 100)) + (16 / 116); 59998 } else { 59999 y = 100 * Math.pow((l + 16) / 116, 3); 60000 y2 = Math.pow(y / 100, 1/3); 60001 } 60002 60003 x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3); 60004 60005 z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3); 60006 60007 return [x, y, z]; 60008} 60009 60010function lab2lch(lab) { 60011 var l = lab[0], 60012 a = lab[1], 60013 b = lab[2], 60014 hr, h, c; 60015 60016 hr = Math.atan2(b, a);
60017 h = hr * 360 / 2 / Math.PI; 60018 if (h < 0) { 60019 h += 360; 60020 } 60021 c = Math.sqrt(a * a + b * b); 60022 return [l, c, h]; 60023} 60024 60025function lab2rgb(args) { 60026 return xyz2rgb(lab2xyz(args)); 60027} 60028 60029function lch2lab(lch) { 60030 var l = lch[0], 60031 c = lch[1], 60032 h = lch[2], 60033 a, b, hr; 60034 60035 hr = h / 360 * 2 * Math.PI; 60036 a = c * Math.cos(hr); 60037 b = c * Math.sin(hr); 60038 return [l, a, b]; 60039} 60040 60041function lch2xyz(args) { 60042 return lab2xyz(lch2lab(args)); 60043} 60044 60045function lch2rgb(args) { 60046 return lab2rgb(lch2lab(args)); 60047} 60048 60049function keyword2rgb(keyword) { 60050 return cssKeywords[keyword]; 60051} 60052 60053function keyword2hsl(args) { 60054 return rgb2hsl(keyword2rgb(args)); 60055} 60056 60057function keyword2hsv(args) { 60058 return rgb2hsv(keyword2rgb(args)); 60059} 60060 60061function keyword2hwb(args) { 60062 return rgb2hwb(keyword2rgb(args)); 60063} 60064 60065function keyword2cmyk(args) { 60066 return rgb2cmyk(keyword2rgb(args)); 60067} 60068 60069function keyword2lab(args) { 60070 return rgb2lab(keyword2rgb(args)); 60071} 60072 60073function keyword2xyz(args) { 60074 return rgb2xyz(keyword2rgb(args)); 60075} 60076 60077var cssKeywords = { 60078 aliceblue: [240,248,255], 60079 antiquewhite: [250,235,215], 60080 aqua: [0,255,255], 60081 aquamarine: [127,255,212], 60082 azure: [240,255,255], 60083 beige: [245,245,220], 60084 bisque: [255,228,196], 60085 black: [0,0,0], 60086 blanchedalmond: [255,235,205], 60087 blue: [0,0,255], 60088 blueviolet: [138,43,226], 60089 brown: [165,42,42], 60090 burlywood: [222,184,135], 60091 cadetblue: [95,158,160], 60092 chartreuse: [127,255,0], 60093 chocolate: [210,105,30], 60094 coral: [255,127,80], 60095 cornflowerblue: [100,149,237], 60096 cornsilk: [255,248,220], 60097 crimson: [220,20,60], 60098 cyan: [0,255,255], 60099 darkblue: [0,0,139], 60100 darkcyan: [0,139,139], 60101 darkgoldenrod: [184,134,11], 60102 darkgray: [169,169,169], 60103 darkgreen: [0,100,0], 60104 darkgrey: [169,169,169], 60105 darkkhaki: [189,183,107], 60106 darkmagenta: [139,0,139], 60107 darkolivegreen: [85,107,47], 60108 darkorange: [255,140,0], 60109 darkorchid: [153,50,204], 60110 darkred: [139,0,0], 60111 darksalmon: [233,150,122], 60112 darkseagreen: [143,188,143], 60113 darkslateblue: [72,61,139], 60114 darkslategray: [47,79,79], 60115 darkslategrey: [47,79,79], 60116 darkturquoise: [0,206,209], 60117 darkviolet: [148,0,211], 60118 deeppink: [255,20,147], 60119 deepskyblue: [0,191,255], 60120 dimgray: [105,105,105], 60121 dimgrey: [105,105,105], 60122 dodgerblue: [30,144,255], 60123 firebrick: [178,34,34], 60124 floralwhite: [255,250,240], 60125 forestgreen: [34,139,34], 60126 fuchsia: [255,0,255], 60127 gainsboro: [220,220,220], 60128 ghostwhite: [248,248,255], 60129 gold: [255,215,0], 60130 goldenrod: [218,165,32], 60131 gray: [128,128,128], 60132 green: [0,128,0], 60133 greenyellow: [173,255,47], 60134 grey: [128,128,128], 60135 honeydew: [240,255,240], 60136 hotpink: [255,105,180], 60137 indianred: [205,92,92], 60138 indigo: [75,0,130], 60139 ivory: [255,255,240], 60140 khaki: [240,230,140], 60141 lavender: [230,230,250], 60142 lavenderblush: [255,240,245], 60143 lawngreen: [124,252,0], 60144 lemonchiffon: [255,250,205], 60145 lightblue: [173,216,230], 60146 lightcoral: [240,128,128], 60147 lightcyan: [224,255,255], 60148 lightgoldenrodyellow: [250,250,210], 60149 lightgray: [211,211,211], 60150 lightgreen: [144,238,144], 60151 lightgrey: [211,211,211], 60152 lightpink: [255,182,193], 60153 lightsalmon: [255,160,122], 60154 lightseagreen: [32,178,170], 60155 lightskyblue: [135,206,250], 60156 lightslategray: [119,136,153], 60157 lightslategrey: [119,136,153], 60158 lightsteelblue: [176,196,222], 60159 lightyellow: [255,255,224], 60160 lime: [0,255,0], 60161 limegreen: [50,205,50], 60162 linen: [250,240,230], 60163 magenta: [255,0,255], 60164 maroon: [128,0,0], 60165 mediumaquamarine: [102,205,170], 60166 mediumblue: [0,0,205], 60167 mediumorchid: [186,85,211], 60168 mediumpurple: [147,112,219], 60169 mediumseagreen: [60,179,113], 60170 mediumslateblue: [123,104,238], 60171 mediumspringgreen: [0,250,154], 60172 mediumturquoise: [72,209,204], 60173 mediumvioletred: [199,21,133], 60174 midnightblue: [25,25,112], 60175 mintcream: [245,255,250], 60176 mistyrose: [255,228,225], 60177 moccasin: [255,228,181], 60178 navajowhite: [255,222,173], 60179 navy: [0,0,128], 60180 oldlace: [253,245,230], 60181 olive: [128,128,0], 60182 olivedrab: [107,142,35], 60183 orange: [255,165,0], 60184 orangered: [255,69,0], 60185 orchid: [218,112,214], 60186 palegoldenrod: [238,232,170], 60187 palegreen: [152,251,152], 60188 paleturquoise: [175,238,238], 60189 palevioletred: [219,112,147], 60190 papayawhip: [255,239,213], 60191 peachpuff: [255,218,185], 60192 peru: [205,133,63], 60193 pink: [255,192,203], 60194 plum: [221,160,221], 60195 powderblue: [176,224,230], 60196 purple: [128,0,128], 60197 rebeccapurple: [102, 51, 153], 60198 red: [255,0,0], 60199 rosybrown: [188,143,143], 60200 royalblue: [65,105,225], 60201 saddlebrown: [139,69,19], 60202 salmon: [250,128,114], 60203 sandybrown: [244,164,96],
60204 seagreen: [46,139,87], 60205 seashell: [255,245,238], 60206 sienna: [160,82,45], 60207 silver: [192,192,192], 60208 skyblue: [135,206,235], 60209 slateblue: [106,90,205], 60210 slategray: [112,128,144], 60211 slategrey: [112,128,144], 60212 snow: [255,250,250], 60213 springgreen: [0,255,127], 60214 steelblue: [70,130,180], 60215 tan: [210,180,140], 60216 teal: [0,128,128], 60217 thistle: [216,191,216], 60218 tomato: [255,99,71], 60219 turquoise: [64,224,208], 60220 violet: [238,130,238], 60221 wheat: [245,222,179], 60222 white: [255,255,255], 60223 whitesmoke: [245,245,245], 60224 yellow: [255,255,0], 60225 yellowgreen: [154,205,50] 60226}; 60227 60228var reverseKeywords = {}; 60229for (var key in cssKeywords) { 60230 reverseKeywords[JSON.stringify(cssKeywords[key])] = key; 60231} 60232 60233var convert = function() { 60234 return new Converter(); 60235}; 60236 60237for (var func in conversions) { 60238 // export Raw versions 60239 convert[func + "Raw"] = (function(func) { 60240 // accept array or plain args 60241 return function(arg) { 60242 if (typeof arg == "number") 60243 arg = Array.prototype.slice.call(arguments); 60244 return conversions[func](arg); 60245 } 60246 })(func); 60247 60248 var pair = /(\w+)2(\w+)/.exec(func), 60249 from = pair[1], 60250 to = pair[2]; 60251 60252 // export rgb2hsl and ["rgb"]["hsl"] 60253 convert[from] = convert[from] || {}; 60254 60255 convert[from][to] = convert[func] = (function(func) { 60256 return function(arg) { 60257 if (typeof arg == "number") 60258 arg = Array.prototype.slice.call(arguments); 60259 60260 var val = conversions[func](arg); 60261 if (typeof val == "string" || val === undefined) 60262 return val; // keyword 60263 60264 for (var i = 0; i < val.length; i++) 60265 val[i] = Math.round(val[i]); 60266 return val; 60267 } 60268 })(func); 60269} 60270 60271 60272/* Converter does lazy conversion and caching */ 60273var Converter = function() { 60274 this.convs = {}; 60275}; 60276 60277/* Either get the values for a space or 60278 set the values for a space, depending on args */ 60279Converter.prototype.routeSpace = function(space, args) { 60280 var values = args[0]; 60281 if (values === undefined) { 60282 // color.rgb() 60283 return this.getValues(space); 60284 } 60285 // color.rgb(10, 10, 10) 60286 if (typeof values == "number") { 60287 values = Array.prototype.slice.call(args); 60288 } 60289 60290 return this.setValues(space, values); 60291}; 60292 60293/* Set the values for a space, invalidating cache */ 60294Converter.prototype.setValues = function(space, values) { 60295 this.space = space; 60296 this.convs = {}; 60297 this.convs[space] = values; 60298 return this; 60299}; 60300 60301/* Get the values for a space. If there's already 60302 a conversion for the space, fetch it, otherwise 60303 compute it */ 60304Converter.prototype.getValues = function(space) { 60305 var vals = this.convs[space]; 60306 if (!vals) { 60307 var fspace = this.space, 60308 from = this.convs[fspace]; 60309 vals = convert[fspace][space](from); 60310 60311 this.convs[space] = vals; 60312 } 60313 return vals; 60314}; 60315 60316["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) { 60317 Converter.prototype[space] = function(vals) { 60318 return this.routeSpace(space, arguments); 60319 }; 60320}); 60321 60322var colorConvert = convert; 60323 60324var colorName = { 60325 "aliceblue": [240, 248, 255], 60326 "antiquewhite": [250, 235, 215], 60327 "aqua": [0, 255, 255], 60328 "aquamarine": [127, 255, 212], 60329 "azure": [240, 255, 255], 60330 "beige": [245, 245, 220], 60331 "bisque": [255, 228, 196], 60332 "black": [0, 0, 0], 60333 "blanchedalmond": [255, 235, 205], 60334 "blue": [0, 0, 255], 60335 "blueviolet": [138, 43, 226], 60336 "brown": [165, 42, 42], 60337 "burlywood": [222, 184, 135], 60338 "cadetblue": [95, 158, 160], 60339 "chartreuse": [127, 255, 0], 60340 "chocolate": [210, 105, 30], 60341 "coral": [255, 127, 80], 60342 "cornflowerblue": [100, 149, 237], 60343 "cornsilk": [255, 248, 220], 60344 "crimson": [220, 20, 60], 60345 "cyan": [0, 255, 255], 60346 "darkblue": [0, 0, 139],
vendor: 90,099 bytes, lines 60347-63954
60347 "darkcyan": [0, 139, 139], 60348 "darkgoldenrod": [184, 134, 11], 60349 "darkgray": [169, 169, 169], 60350 "darkgreen": [0, 100, 0], 60351 "darkgrey": [169, 169, 169], 60352 "darkkhaki": [189, 183, 107], 60353 "darkmagenta": [139, 0, 139], 60354 "darkolivegreen": [85, 107, 47], 60355 "darkorange": [255, 140, 0], 60356 "darkorchid": [153, 50, 204], 60357 "darkred": [139, 0, 0], 60358 "darksalmon": [233, 150, 122], 60359 "darkseagreen": [143, 188, 143], 60360 "darkslateblue": [72, 61, 139], 60361 "darkslategray": [47, 79, 79], 60362 "darkslategrey": [47, 79, 79], 60363 "darkturquoise": [0, 206, 209], 60364 "darkviolet": [148, 0, 211], 60365 "deeppink": [255, 20, 147], 60366 "deepskyblue": [0, 191, 255], 60367 "dimgray": [105, 105, 105], 60368 "dimgrey": [105, 105, 105], 60369 "dodgerblue": [30, 144, 255], 60370 "firebrick": [178, 34, 34], 60371 "floralwhite": [255, 250, 240], 60372 "forestgreen": [34, 139, 34], 60373 "fuchsia": [255, 0, 255], 60374 "gainsboro": [220, 220, 220], 60375 "ghostwhite": [248, 248, 255], 60376 "gold": [255, 215, 0], 60377 "goldenrod": [218, 165, 32], 60378 "gray": [128, 128, 128], 60379 "green": [0, 128, 0], 60380 "greenyellow": [173, 255, 47], 60381 "grey": [128, 128, 128], 60382 "honeydew": [240, 255, 240], 60383 "hotpink": [255, 105, 180], 60384 "indianred": [205, 92, 92], 60385 "indigo": [75, 0, 130], 60386 "ivory": [255, 255, 240], 60387 "khaki": [240, 230, 140], 60388 "lavender": [230, 230, 250], 60389 "lavenderblush": [255, 240, 245], 60390 "lawngreen": [124, 252, 0], 60391 "lemonchiffon": [255, 250, 205], 60392 "lightblue": [173, 216, 230], 60393 "lightcoral": [240, 128, 128], 60394 "lightcyan": [224, 255, 255], 60395 "lightgoldenrodyellow": [250, 250, 210], 60396 "lightgray": [211, 211, 211], 60397 "lightgreen": [144, 238, 144], 60398 "lightgrey": [211, 211, 211], 60399 "lightpink": [255, 182, 193], 60400 "lightsalmon": [255, 160, 122], 60401 "lightseagreen": [32, 178, 170], 60402 "lightskyblue": [135, 206, 250], 60403 "lightslategray": [119, 136, 153], 60404 "lightslategrey": [119, 136, 153], 60405 "lightsteelblue": [176, 196, 222], 60406 "lightyellow": [255, 255, 224], 60407 "lime": [0, 255, 0], 60408 "limegreen": [50, 205, 50], 60409 "linen": [250, 240, 230], 60410 "magenta": [255, 0, 255], 60411 "maroon": [128, 0, 0], 60412 "mediumaquamarine": [102, 205, 170], 60413 "mediumblue": [0, 0, 205], 60414 "mediumorchid": [186, 85, 211], 60415 "mediumpurple": [147, 112, 219], 60416 "mediumseagreen": [60, 179, 113], 60417 "mediumslateblue": [123, 104, 238], 60418 "mediumspringgreen": [0, 250, 154], 60419 "mediumturquoise": [72, 209, 204], 60420 "mediumvioletred": [199, 21, 133], 60421 "midnightblue": [25, 25, 112], 60422 "mintcream": [245, 255, 250], 60423 "mistyrose": [255, 228, 225], 60424 "moccasin": [255, 228, 181], 60425 "navajowhite": [255, 222, 173], 60426 "navy": [0, 0, 128], 60427 "oldlace": [253, 245, 230], 60428 "olive": [128, 128, 0], 60429 "olivedrab": [107, 142, 35], 60430 "orange": [255, 165, 0], 60431 "orangered": [255, 69, 0], 60432 "orchid": [218, 112, 214], 60433 "palegoldenrod": [238, 232, 170], 60434 "palegreen": [152, 251, 152], 60435 "paleturquoise": [175, 238, 238], 60436 "palevioletred": [219, 112, 147], 60437 "papayawhip": [255, 239, 213], 60438 "peachpuff": [255, 218, 185], 60439 "peru": [205, 133, 63], 60440 "pink": [255, 192, 203], 60441 "plum": [221, 160, 221], 60442 "powderblue": [176, 224, 230], 60443 "purple": [128, 0, 128], 60444 "rebeccapurple": [102, 51, 153], 60445 "red": [255, 0, 0], 60446 "rosybrown": [188, 143, 143], 60447 "royalblue": [65, 105, 225], 60448 "saddlebrown": [139, 69, 19], 60449 "salmon": [250, 128, 114], 60450 "sandybrown": [244, 164, 96], 60451 "seagreen": [46, 139, 87], 60452 "seashell": [255, 245, 238], 60453 "sienna": [160, 82, 45], 60454 "silver": [192, 192, 192], 60455 "skyblue": [135, 206, 235], 60456 "slateblue": [106, 90, 205], 60457 "slategray": [112, 128, 144], 60458 "slategrey": [112, 128, 144], 60459 "snow": [255, 250, 250], 60460 "springgreen": [0, 255, 127], 60461 "steelblue": [70, 130, 180], 60462 "tan": [210, 180, 140], 60463 "teal": [0, 128, 128], 60464 "thistle": [216, 191, 216], 60465 "tomato": [255, 99, 71], 60466 "turquoise": [64, 224, 208], 60467 "violet": [238, 130, 238], 60468 "wheat": [245, 222, 179], 60469 "white": [255, 255, 255], 60470 "whitesmoke": [245, 245, 245], 60471 "yellow": [255, 255, 0], 60472 "yellowgreen": [154, 205, 50] 60473}; 60474 60475/* MIT license */ 60476 60477 60478var colorString = { 60479 getRgba: getRgba, 60480 getHsla: getHsla, 60481 getRgb: getRgb, 60482 getHsl: getHsl, 60483 getHwb: getHwb, 60484 getAlpha: getAlpha, 60485 60486 hexString: hexString, 60487 rgbString: rgbString, 60488 rgbaString: rgbaString, 60489 percentString: percentString, 60490 percentaString: percentaString, 60491 hslString: hslString, 60492 hslaString: hslaString, 60493 hwbString: hwbString, 60494 keyword: keyword 60495}; 60496 60497function getRgba(string) { 60498 if (!string) { 60499 return; 60500 } 60501 var abbr = /^#([a-fA-F0-9]{3,4})$/i, 60502 hex = /^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i, 60503 rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, 60504 per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, 60505 keyword = /(\w+)/; 60506 60507 var rgb = [0, 0, 0], 60508 a = 1, 60509 match = string.match(abbr), 60510 hexAlpha = ""; 60511 if (match) { 60512 match = match[1]; 60513 hexAlpha = match[3]; 60514 for (var i = 0; i < rgb.length; i++) { 60515 rgb[i] = parseInt(match[i] + match[i], 16); 60516 } 60517 if (hexAlpha) { 60518 a = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100; 60519 } 60520 } 60521 else if (match = string.match(hex)) { 60522 hexAlpha = match[2]; 60523 match = match[1]; 60524 for (var i = 0; i < rgb.length; i++) { 60525 rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); 60526 } 60527 if (hexAlpha) { 60528 a = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100; 60529 } 60530 } 60531 else if (match = string.match(rgba)) { 60532 for (var i = 0; i < rgb.length; i++) { 60533 rgb[i] = parseInt(match[i + 1]); 60534 } 60535 a = parseFloat(match[4]); 60536 } 60537 else if (match = string.match(per)) { 60538 for (var i = 0; i < rgb.length; i++) { 60539 rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); 60540 } 60541 a = parseFloat(match[4]); 60542 } 60543 else if (match = string.match(keyword)) { 60544 if (match[1] == "transparent") { 60545 return [0, 0, 0, 0]; 60546 } 60547 rgb = colorName[match[1]]; 60548 if (!rgb) { 60549 return; 60550 } 60551 } 60552 60553 for (var i = 0; i < rgb.length; i++) { 60554 rgb[i] = scale(rgb[i], 0, 255); 60555 } 60556 if (!a && a != 0) { 60557 a = 1; 60558 } 60559 else { 60560 a = scale(a, 0, 1); 60561 } 60562 rgb[3] = a; 60563 return rgb; 60564} 60565 60566function getHsla(string) { 60567 if (!string) { 60568 return; 60569 } 60570 var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; 60571 var match = string.match(hsl); 60572 if (match) { 60573 var alpha = parseFloat(match[4]); 60574 var h = scale(parseInt(match[1]), 0, 360), 60575 s = scale(parseFloat(match[2]), 0, 100), 60576 l = scale(parseFloat(match[3]), 0, 100), 60577 a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); 60578 return [h, s, l, a]; 60579 } 60580} 60581 60582function getHwb(string) { 60583 if (!string) { 60584 return; 60585 } 60586 var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; 60587 var match = string.match(hwb); 60588 if (match) { 60589 var alpha = parseFloat(match[4]); 60590 var h = scale(parseInt(match[1]), 0, 360), 60591 w = scale(parseFloat(match[2]), 0, 100), 60592 b = scale(parseFloat(match[3]), 0, 100), 60593 a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); 60594 return [h, w, b, a]; 60595 } 60596} 60597 60598function getRgb(string) { 60599 var rgba = getRgba(string); 60600 return rgba && rgba.slice(0, 3); 60601} 60602 60603function getHsl(string) { 60604 var hsla = getHsla(string); 60605 return hsla && hsla.slice(0, 3); 60606} 60607 60608function getAlpha(string) { 60609 var vals = getRgba(string); 60610 if (vals) { 60611 return vals[3]; 60612 } 60613 else if (vals = getHsla(string)) { 60614 return vals[3]; 60615 } 60616 else if (vals = getHwb(string)) { 60617 return vals[3]; 60618 } 60619} 60620 60621// generators 60622function hexString(rgba, a) { 60623 var a = (a !== undefined && rgba.length === 3) ? a : rgba[3]; 60624 return "#" + hexDouble(rgba[0]) 60625 + hexDouble(rgba[1]) 60626 + hexDouble(rgba[2]) 60627 + ( 60628 (a >= 0 && a < 1) 60629 ? hexDouble(Math.round(a * 255)) 60630 : "" 60631 ); 60632} 60633 60634function rgbString(rgba, alpha) { 60635 if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { 60636 return rgbaString(rgba, alpha); 60637 } 60638 return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; 60639} 60640 60641function rgbaString(rgba, alpha) { 60642 if (alpha === undefined) { 60643 alpha = (rgba[3] !== undefined ? rgba[3] : 1); 60644 } 60645 return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] 60646 + ", " + alpha + ")"; 60647} 60648 60649function percentString(rgba, alpha) { 60650 if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { 60651 return percentaString(rgba, alpha); 60652 } 60653 var r = Math.round(rgba[0]/255 * 100), 60654 g = Math.round(rgba[1]/255 * 100), 60655 b = Math.round(rgba[2]/255 * 100); 60656 60657 return "rgb(" + r + "%, " + g + "%, " + b + "%)"; 60658} 60659 60660function percentaString(rgba, alpha) { 60661 var r = Math.round(rgba[0]/255 * 100), 60662 g = Math.round(rgba[1]/255 * 100), 60663 b = Math.round(rgba[2]/255 * 100); 60664 return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; 60665} 60666 60667function hslString(hsla, alpha) { 60668 if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { 60669 return hslaString(hsla, alpha); 60670 } 60671 return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; 60672} 60673 60674function hslaString(hsla, alpha) { 60675 if (alpha === undefined) { 60676 alpha = (hsla[3] !== undefined ? hsla[3] : 1); 60677 } 60678 return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " 60679 + alpha + ")"; 60680} 60681 60682// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax 60683// (hwb have alpha optional & 1 is default value) 60684function hwbString(hwb, alpha) { 60685 if (alpha === undefined) { 60686 alpha = (hwb[3] !== undefined ? hwb[3] : 1); 60687 } 60688 return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" 60689 + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; 60690} 60691 60692function keyword(rgb) { 60693 return reverseNames[rgb.slice(0, 3)]; 60694} 60695 60696// helpers 60697function scale(num, min, max) { 60698 return Math.min(Math.max(min, num), max); 60699} 60700 60701function hexDouble(num) { 60702 var str = num.toString(16).toUpperCase(); 60703 return (str.length < 2) ? "0" + str : str; 60704} 60705 60706 60707//create a list of reverse color names 60708var reverseNames = {}; 60709for (var name in colorName) { 60710 reverseNames[colorName[name]] = name; 60711} 60712 60713/* MIT license */ 60714 60715 60716 60717var Color = function (obj) { 60718 if (obj instanceof Color) { 60719 return obj; 60720 } 60721 if (!(this instanceof Color)) { 60722 return new Color(obj); 60723 } 60724 60725 this.valid = false; 60726 this.values = { 60727 rgb: [0, 0, 0], 60728 hsl: [0, 0, 0], 60729 hsv: [0, 0, 0], 60730 hwb: [0, 0, 0], 60731 cmyk: [0, 0, 0, 0], 60732 alpha: 1 60733 }; 60734 60735 // parse Color() argument 60736 var vals; 60737 if (typeof obj === 'string') { 60738 vals = colorString.getRgba(obj); 60739 if (vals) { 60740 this.setValues('rgb', vals); 60741 } else if (vals = colorString.getHsla(obj)) { 60742 this.setValues('hsl', vals); 60743 } else if (vals = colorString.getHwb(obj)) { 60744 this.setValues('hwb', vals); 60745 } 60746 } else if (typeof obj === 'object') { 60747 vals = obj; 60748 if (vals.r !== undefined || vals.red !== undefined) { 60749 this.setValues('rgb', vals); 60750 } else if (vals.l !== undefined || vals.lightness !== undefined) { 60751 this.setValues('hsl', vals); 60752 } else if (vals.v !== undefined || vals.value !== undefined) { 60753 this.setValues('hsv', vals); 60754 } else if (vals.w !== undefined || vals.whiteness !== undefined) { 60755 this.setValues('hwb', vals); 60756 } else if (vals.c !== undefined || vals.cyan !== undefined) { 60757 this.setValues('cmyk', vals); 60758 } 60759 } 60760}; 60761 60762Color.prototype = { 60763 isValid: function () { 60764 return this.valid; 60765 }, 60766 rgb: function () { 60767 return this.setSpace('rgb', arguments); 60768 }, 60769 hsl: function () { 60770 return this.setSpace('hsl', arguments); 60771 }, 60772 hsv: function () { 60773 return this.setSpace('hsv', arguments); 60774 }, 60775 hwb: function () { 60776 return this.setSpace('hwb', arguments); 60777 }, 60778 cmyk: function () { 60779 return this.setSpace('cmyk', arguments); 60780 }, 60781 60782 rgbArray: function () { 60783 return this.values.rgb; 60784 }, 60785 hslArray: function () { 60786 return this.values.hsl; 60787 }, 60788 hsvArray: function () { 60789 return this.values.hsv; 60790 }, 60791 hwbArray: function () { 60792 var values = this.values; 60793 if (values.alpha !== 1) { 60794 return values.hwb.concat([values.alpha]); 60795 } 60796 return values.hwb; 60797 }, 60798 cmykArray: function () { 60799 return this.values.cmyk; 60800 }, 60801 rgbaArray: function () { 60802 var values = this.values; 60803 return values.rgb.concat([values.alpha]); 60804 }, 60805 hslaArray: function () { 60806 var values = this.values; 60807 return values.hsl.concat([values.alpha]); 60808 }, 60809 alpha: function (val) { 60810 if (val === undefined) { 60811 return this.values.alpha; 60812 } 60813 this.setValues('alpha', val); 60814 return this; 60815 }, 60816 60817 red: function (val) { 60818 return this.setChannel('rgb', 0, val); 60819 }, 60820 green: function (val) { 60821 return this.setChannel('rgb', 1, val); 60822 }, 60823 blue: function (val) { 60824 return this.setChannel('rgb', 2, val); 60825 }, 60826 hue: function (val) { 60827 if (val) { 60828 val %= 360; 60829 val = val < 0 ? 360 + val : val; 60830 } 60831 return this.setChannel('hsl', 0, val); 60832 }, 60833 saturation: function (val) { 60834 return this.setChannel('hsl', 1, val); 60835 }, 60836 lightness: function (val) { 60837 return this.setChannel('hsl', 2, val); 60838 }, 60839 saturationv: function (val) { 60840 return this.setChannel('hsv', 1, val); 60841 }, 60842 whiteness: function (val) { 60843 return this.setChannel('hwb', 1, val); 60844 }, 60845 blackness: function (val) { 60846 return this.setChannel('hwb', 2, val); 60847 }, 60848 value: function (val) { 60849 return this.setChannel('hsv', 2, val); 60850 }, 60851 cyan: function (val) { 60852 return this.setChannel('cmyk', 0, val); 60853 }, 60854 magenta: function (val) { 60855 return this.setChannel('cmyk', 1, val); 60856 }, 60857 yellow: function (val) { 60858 return this.setChannel('cmyk', 2, val); 60859 }, 60860 black: function (val) { 60861 return this.setChannel('cmyk', 3, val); 60862 }, 60863 60864 hexString: function () { 60865 return colorString.hexString(this.values.rgb); 60866 }, 60867 rgbString: function () { 60868 return colorString.rgbString(this.values.rgb, this.values.alpha); 60869 }, 60870 rgbaString: function () { 60871 return colorString.rgbaString(this.values.rgb, this.values.alpha); 60872 }, 60873 percentString: function () { 60874 return colorString.percentString(this.values.rgb, this.values.alpha); 60875 }, 60876 hslString: function () { 60877 return colorString.hslString(this.values.hsl, this.values.alpha); 60878 }, 60879 hslaString: function () { 60880 return colorString.hslaString(this.values.hsl, this.values.alpha); 60881 }, 60882 hwbString: function () { 60883 return colorString.hwbString(this.values.hwb, this.values.alpha); 60884 }, 60885 keyword: function () { 60886 return colorString.keyword(this.values.rgb, this.values.alpha); 60887 }, 60888 60889 rgbNumber: function () { 60890 var rgb = this.values.rgb; 60891 return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; 60892 }, 60893 60894 luminosity: function () { 60895 // http://www.w3.org/TR/WCAG20/#relativeluminancedef 60896 var rgb = this.values.rgb; 60897 var lum = []; 60898 for (var i = 0; i < rgb.length; i++) { 60899 var chan = rgb[i] / 255; 60900 lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); 60901 } 60902 return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; 60903 }, 60904 60905 contrast: function (color2) { 60906 // http://www.w3.org/TR/WCAG20/#contrast-ratiodef 60907 var lum1 = this.luminosity(); 60908 var lum2 = color2.luminosity(); 60909 if (lum1 > lum2) { 60910 return (lum1 + 0.05) / (lum2 + 0.05); 60911 } 60912 return (lum2 + 0.05) / (lum1 + 0.05); 60913 }, 60914 60915 level: function (color2) { 60916 var contrastRatio = this.contrast(color2); 60917 if (contrastRatio >= 7.1) { 60918 return 'AAA'; 60919 } 60920 60921 return (contrastRatio >= 4.5) ? 'AA' : ''; 60922 }, 60923 60924 dark: function () { 60925 // YIQ equation from http://24ways.org/2010/calculating-color-contrast 60926 var rgb = this.values.rgb; 60927 var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; 60928 return yiq < 128; 60929 }, 60930 60931 light: function () { 60932 return !this.dark(); 60933 }, 60934 60935 negate: function () { 60936 var rgb = []; 60937 for (var i = 0; i < 3; i++) { 60938 rgb[i] = 255 - this.values.rgb[i]; 60939 } 60940 this.setValues('rgb', rgb); 60941 return this; 60942 }, 60943 60944 lighten: function (ratio) { 60945 var hsl = this.values.hsl; 60946 hsl[2] += hsl[2] * ratio; 60947 this.setValues('hsl', hsl); 60948 return this; 60949 }, 60950 60951 darken: function (ratio) { 60952 var hsl = this.values.hsl; 60953 hsl[2] -= hsl[2] * ratio; 60954 this.setValues('hsl', hsl); 60955 return this; 60956 }, 60957 60958 saturate: function (ratio) { 60959 var hsl = this.values.hsl; 60960 hsl[1] += hsl[1] * ratio; 60961 this.setValues('hsl', hsl); 60962 return this; 60963 }, 60964 60965 desaturate: function (ratio) { 60966 var hsl = this.values.hsl; 60967 hsl[1] -= hsl[1] * ratio; 60968 this.setValues('hsl', hsl); 60969 return this; 60970 }, 60971 60972 whiten: function (ratio) { 60973 var hwb = this.values.hwb; 60974 hwb[1] += hwb[1] * ratio; 60975 this.setValues('hwb', hwb); 60976 return this; 60977 }, 60978 60979 blacken: function (ratio) { 60980 var hwb = this.values.hwb; 60981 hwb[2] += hwb[2] * ratio; 60982 this.setValues('hwb', hwb); 60983 return this; 60984 }, 60985 60986 greyscale: function () { 60987 var rgb = this.values.rgb; 60988 // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 60989 var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; 60990 this.setValues('rgb', [val, val, val]); 60991 return this; 60992 }, 60993 60994 clearer: function (ratio) { 60995 var alpha = this.values.alpha; 60996 this.setValues('alpha', alpha - (alpha * ratio)); 60997 return this; 60998 }, 60999 61000 opaquer: function (ratio) { 61001 var alpha = this.values.alpha; 61002 this.setValues('alpha', alpha + (alpha * ratio)); 61003 return this; 61004 }, 61005 61006 rotate: function (degrees) { 61007 var hsl = this.values.hsl; 61008 var hue = (hsl[0] + degrees) % 360; 61009 hsl[0] = hue < 0 ? 360 + hue : hue; 61010 this.setValues('hsl', hsl); 61011 return this; 61012 }, 61013 61014 /** 61015 * Ported from sass implementation in C 61016 * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 61017 */ 61018 mix: function (mixinColor, weight) { 61019 var color1 = this; 61020 var color2 = mixinColor; 61021 var p = weight === undefined ? 0.5 : weight; 61022 61023 var w = 2 * p - 1; 61024 var a = color1.alpha() - color2.alpha(); 61025 61026 var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; 61027 var w2 = 1 - w1; 61028 61029 return this 61030 .rgb( 61031 w1 * color1.red() + w2 * color2.red(), 61032 w1 * color1.green() + w2 * color2.green(), 61033 w1 * color1.blue() + w2 * color2.blue() 61034 ) 61035 .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); 61036 }, 61037 61038 toJSON: function () { 61039 return this.rgb(); 61040 }, 61041 61042 clone: function () { 61043 // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, 61044 // making the final build way to big to embed in Chart.js. So let's do it manually, 61045 // assuming that values to clone are 1 dimension arrays containing only numbers, 61046 // except 'alpha' which is a number. 61047 var result = new Color(); 61048 var source = this.values; 61049 var target = result.values; 61050 var value, type; 61051 61052 for (var prop in source) { 61053 if (source.hasOwnProperty(prop)) { 61054 value = source[prop]; 61055 type = ({}).toString.call(value); 61056 if (type === '[object Array]') { 61057 target[prop] = value.slice(0); 61058 } else if (type === '[object Number]') { 61059 target[prop] = value; 61060 } else { 61061 console.error('unexpected color value:', value); 61062 } 61063 } 61064 } 61065 61066 return result; 61067 } 61068}; 61069 61070Color.prototype.spaces = { 61071 rgb: ['red', 'green', 'blue'], 61072 hsl: ['hue', 'saturation', 'lightness'], 61073 hsv: ['hue', 'saturation', 'value'], 61074 hwb: ['hue', 'whiteness', 'blackness'], 61075 cmyk: ['cyan', 'magenta', 'yellow', 'black'] 61076}; 61077 61078Color.prototype.maxes = { 61079 rgb: [255, 255, 255], 61080 hsl: [360, 100, 100], 61081 hsv: [360, 100, 100], 61082 hwb: [360, 100, 100], 61083 cmyk: [100, 100, 100, 100] 61084}; 61085 61086Color.prototype.getValues = function (space) { 61087 var values = this.values; 61088 var vals = {}; 61089 61090 for (var i = 0; i < space.length; i++) { 61091 vals[space.charAt(i)] = values[space][i]; 61092 } 61093 61094 if (values.alpha !== 1) { 61095 vals.a = values.alpha; 61096 } 61097 61098 // {r: 255, g: 255, b: 255, a: 0.4} 61099 return vals; 61100}; 61101 61102Color.prototype.setValues = function (space, vals) { 61103 var values = this.values; 61104 var spaces = this.spaces; 61105 var maxes = this.maxes; 61106 var alpha = 1; 61107 var i; 61108 61109 this.valid = true; 61110 61111 if (space === 'alpha') { 61112 alpha = vals; 61113 } else if (vals.length) { 61114 // [10, 10, 10] 61115 values[space] = vals.slice(0, space.length); 61116 alpha = vals[space.length]; 61117 } else if (vals[space.charAt(0)] !== undefined) { 61118 // {r: 10, g: 10, b: 10} 61119 for (i = 0; i < space.length; i++) { 61120 values[space][i] = vals[space.charAt(i)]; 61121 } 61122 61123 alpha = vals.a; 61124 } else if (vals[spaces[space][0]] !== undefined) { 61125 // {red: 10, green: 10, blue: 10} 61126 var chans = spaces[space]; 61127 61128 for (i = 0; i < space.length; i++) { 61129 values[space][i] = vals[chans[i]]; 61130 } 61131 61132 alpha = vals.alpha; 61133 } 61134 61135 values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); 61136 61137 if (space === 'alpha') { 61138 return false; 61139 } 61140 61141 var capped; 61142 61143 // cap values of the space prior converting all values 61144 for (i = 0; i < space.length; i++) { 61145 capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); 61146 values[space][i] = Math.round(capped); 61147 } 61148 61149 // convert to all the other color spaces 61150 for (var sname in spaces) { 61151 if (sname !== space) { 61152 values[sname] = colorConvert[space][sname](values[space]); 61153 } 61154 } 61155 61156 return true; 61157}; 61158 61159Color.prototype.setSpace = function (space, args) { 61160 var vals = args[0]; 61161 61162 if (vals === undefined) { 61163 // color.rgb() 61164 return this.getValues(space); 61165 } 61166 61167 // color.rgb(10, 10, 10) 61168 if (typeof vals === 'number') { 61169 vals = Array.prototype.slice.call(args); 61170 } 61171 61172 this.setValues(space, vals); 61173 return this; 61174}; 61175 61176Color.prototype.setChannel = function (space, index, val) { 61177 var svalues = this.values[space]; 61178 if (val === undefined) { 61179 // color.red() 61180 return svalues[index]; 61181 } else if (val === svalues[index]) { 61182 // color.red(color.red()) 61183 return this; 61184 } 61185 61186 // color.red(100) 61187 svalues[index] = val; 61188 this.setValues(space, svalues); 61189 61190 return this; 61191}; 61192 61193if (typeof window !== 'undefined') { 61194 window.Color = Color; 61195} 61196 61197var chartjsColor = Color; 61198 61199/** 61200 * @namespace Chart.helpers 61201 */ 61202var helpers = { 61203 /** 61204 * An empty function that can be used, for example, for optional callback. 61205 */ 61206 noop: function() {}, 61207 61208 /** 61209 * Returns a unique id, sequentially generated from a global variable. 61210 * @returns {number} 61211 * @function 61212 */ 61213 uid: (function() { 61214 var id = 0; 61215 return function() { 61216 return id++; 61217 }; 61218 }()), 61219 61220 /** 61221 * Returns true if `value` is neither null nor undefined, else returns false. 61222 * @param {*} value - The value to test. 61223 * @returns {boolean} 61224 * @since 2.7.0 61225 */ 61226 isNullOrUndef: function(value) { 61227 return value === null || typeof value === 'undefined'; 61228 }, 61229 61230 /** 61231 * Returns true if `value` is an array (including typed arrays), else returns false. 61232 * @param {*} value - The value to test. 61233 * @returns {boolean} 61234 * @function 61235 */ 61236 isArray: function(value) { 61237 if (Array.isArray && Array.isArray(value)) { 61238 return true; 61239 } 61240 var type = Object.prototype.toString.call(value); 61241 if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') { 61242 return true; 61243 } 61244 return false; 61245 }, 61246 61247 /** 61248 * Returns true if `value` is an object (excluding null), else returns false. 61249 * @param {*} value - The value to test. 61250 * @returns {boolean} 61251 * @since 2.7.0 61252 */ 61253 isObject: function(value) { 61254 return value !== null && Object.prototype.toString.call(value) === '[object Object]'; 61255 }, 61256 61257 /** 61258 * Returns true if `value` is a finite number, else returns false 61259 * @param {*} value - The value to test. 61260 * @returns {boolean} 61261 */ 61262 isFinite: function(value) { 61263 return (typeof value === 'number' || value instanceof Number) && isFinite(value); 61264 }, 61265 61266 /** 61267 * Returns `value` if defined, else returns `defaultValue`. 61268 * @param {*} value - The value to return if defined. 61269 * @param {*} defaultValue - The value to return if `value` is undefined. 61270 * @returns {*} 61271 */ 61272 valueOrDefault: function(value, defaultValue) { 61273 return typeof value === 'undefined' ? defaultValue : value; 61274 }, 61275 61276 /** 61277 * Returns value at the given `index` in array if defined, else returns `defaultValue`. 61278 * @param {Array} value - The array to lookup for value at `index`. 61279 * @param {number} index - The index in `value` to lookup for value. 61280 * @param {*} defaultValue - The value to return if `value[index]` is undefined. 61281 * @returns {*} 61282 */ 61283 valueAtIndexOrDefault: function(value, index, defaultValue) { 61284 return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue); 61285 }, 61286 61287 /** 61288 * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the 61289 * value returned by `fn`. If `fn` is not a function, this method returns undefined. 61290 * @param {function} fn - The function to call. 61291 * @param {Array|undefined|null} args - The arguments with which `fn` should be called. 61292 * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. 61293 * @returns {*} 61294 */ 61295 callback: function(fn, args, thisArg) { 61296 if (fn && typeof fn.call === 'function') { 61297 return fn.apply(thisArg, args); 61298 } 61299 }, 61300 61301 /** 61302 * Note(SB) for performance sake, this method should only be used when loopable type 61303 * is unknown or in none intensive code (not called often and small loopable). Else 61304 * it's preferable to use a regular for() loop and save extra function calls. 61305 * @param {object|Array} loopable - The object or array to be iterated. 61306 * @param {function} fn - The function to call for each item. 61307 * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. 61308 * @param {boolean} [reverse] - If true, iterates backward on the loopable. 61309 */ 61310 each: function(loopable, fn, thisArg, reverse) { 61311 var i, len, keys; 61312 if (helpers.isArray(loopable)) { 61313 len = loopable.length; 61314 if (reverse) { 61315 for (i = len - 1; i >= 0; i--) { 61316 fn.call(thisArg, loopable[i], i); 61317 } 61318 } else { 61319 for (i = 0; i < len; i++) { 61320 fn.call(thisArg, loopable[i], i); 61321 } 61322 } 61323 } else if (helpers.isObject(loopable)) { 61324 keys = Object.keys(loopable); 61325 len = keys.length; 61326 for (i = 0; i < len; i++) { 61327 fn.call(thisArg, loopable[keys[i]], keys[i]); 61328 } 61329 } 61330 }, 61331 61332 /** 61333 * Returns true if the `a0` and `a1` arrays have the same content, else returns false. 61334 * @see https://stackoverflow.com/a/14853974 61335 * @param {Array} a0 - The array to compare 61336 * @param {Array} a1 - The array to compare 61337 * @returns {boolean} 61338 */ 61339 arrayEquals: function(a0, a1) { 61340 var i, ilen, v0, v1; 61341 61342 if (!a0 || !a1 || a0.length !== a1.length) { 61343 return false; 61344 } 61345 61346 for (i = 0, ilen = a0.length; i < ilen; ++i) { 61347 v0 = a0[i]; 61348 v1 = a1[i]; 61349 61350 if (v0 instanceof Array && v1 instanceof Array) { 61351 if (!helpers.arrayEquals(v0, v1)) { 61352 return false; 61353 } 61354 } else if (v0 !== v1) { 61355 // NOTE: two different object instances will never be equal: {x:20} != {x:20} 61356 return false; 61357 } 61358 } 61359 61360 return true; 61361 }, 61362 61363 /** 61364 * Returns a deep copy of `source` without keeping references on objects and arrays. 61365 * @param {*} source - The value to clone. 61366 * @returns {*} 61367 */ 61368 clone: function(source) { 61369 if (helpers.isArray(source)) { 61370 return source.map(helpers.clone); 61371 } 61372 61373 if (helpers.isObject(source)) { 61374 var target = {}; 61375 var keys = Object.keys(source); 61376 var klen = keys.length; 61377 var k = 0; 61378 61379 for (; k < klen; ++k) { 61380 target[keys[k]] = helpers.clone(source[keys[k]]); 61381 } 61382 61383 return target; 61384 } 61385 61386 return source; 61387 }, 61388 61389 /** 61390 * The default merger when Chart.helpers.merge is called without merger option. 61391 * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback. 61392 * @private 61393 */ 61394 _merger: function(key, target, source, options) { 61395 var tval = target[key]; 61396 var sval = source[key]; 61397 61398 if (helpers.isObject(tval) && helpers.isObject(sval)) { 61399 helpers.merge(tval, sval, options); 61400 } else { 61401 target[key] = helpers.clone(sval); 61402 } 61403 }, 61404 61405 /** 61406 * Merges source[key] in target[key] only if target[key] is undefined. 61407 * @private 61408 */ 61409 _mergerIf: function(key, target, source) { 61410 var tval = target[key]; 61411 var sval = source[key]; 61412 61413 if (helpers.isObject(tval) && helpers.isObject(sval)) { 61414 helpers.mergeIf(tval, sval); 61415 } else if (!target.hasOwnProperty(key)) { 61416 target[key] = helpers.clone(sval); 61417 } 61418 }, 61419 61420 /** 61421 * Recursively deep copies `source` properties into `target` with the given `options`. 61422 * IMPORTANT: `target` is not cloned and will be updated with `source` properties. 61423 * @param {object} target - The target object in which all sources are merged into. 61424 * @param {object|object[]} source - Object(s) to merge into `target`. 61425 * @param {object} [options] - Merging options: 61426 * @param {function} [options.merger] - The merge method (key, target, source, options) 61427 * @returns {object} The `target` object. 61428 */ 61429 merge: function(target, source, options) { 61430 var sources = helpers.isArray(source) ? source : [source]; 61431 var ilen = sources.length; 61432 var merge, i, keys, klen, k; 61433 61434 if (!helpers.isObject(target)) { 61435 return target; 61436 } 61437 61438 options = options || {}; 61439 merge = options.merger || helpers._merger; 61440 61441 for (i = 0; i < ilen; ++i) { 61442 source = sources[i]; 61443 if (!helpers.isObject(source)) { 61444 continue; 61445 } 61446 61447 keys = Object.keys(source); 61448 for (k = 0, klen = keys.length; k < klen; ++k) { 61449 merge(keys[k], target, source, options); 61450 } 61451 } 61452 61453 return target; 61454 }, 61455 61456 /** 61457 * Recursively deep copies `source` properties into `target` *only* if not defined in target. 61458 * IMPORTANT: `target` is not cloned and will be updated with `source` properties. 61459 * @param {object} target - The target object in which all sources are merged into. 61460 * @param {object|object[]} source - Object(s) to merge into `target`. 61461 * @returns {object} The `target` object. 61462 */ 61463 mergeIf: function(target, source) { 61464 return helpers.merge(target, source, {merger: helpers._mergerIf}); 61465 }, 61466 61467 /** 61468 * Applies the contents of two or more objects together into the first object. 61469 * @param {object} target - The target object in which all objects are merged into. 61470 * @param {object} arg1 - Object containing additional properties to merge in target. 61471 * @param {object} argN - Additional objects containing properties to merge in target. 61472 * @returns {object} The `target` object. 61473 */ 61474 extend: function(target) { 61475 var setFn = function(value, key) { 61476 target[key] = value; 61477 }; 61478 for (var i = 1, ilen = arguments.length; i < ilen; ++i) { 61479 helpers.each(arguments[i], setFn); 61480 } 61481 return target; 61482 }, 61483 61484 /** 61485 * Basic javascript inheritance based on the model created in Backbone.js 61486 */ 61487 inherits: function(extensions) { 61488 var me = this; 61489 var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { 61490 return me.apply(this, arguments); 61491 }; 61492 61493 var Surrogate = function() { 61494 this.constructor = ChartElement; 61495 }; 61496 61497 Surrogate.prototype = me.prototype; 61498 ChartElement.prototype = new Surrogate(); 61499 ChartElement.extend = helpers.inherits; 61500 61501 if (extensions) { 61502 helpers.extend(ChartElement.prototype, extensions); 61503 } 61504 61505 ChartElement.__super__ = me.prototype; 61506 return ChartElement; 61507 } 61508}; 61509 61510var helpers_core = helpers; 61511 61512// DEPRECATIONS 61513 61514/** 61515 * Provided for backward compatibility, use Chart.helpers.callback instead. 61516 * @function Chart.helpers.callCallback 61517 * @deprecated since version 2.6.0 61518 * @todo remove at version 3 61519 * @private 61520 */ 61521helpers.callCallback = helpers.callback; 61522 61523/** 61524 * Provided for backward compatibility, use Array.prototype.indexOf instead. 61525 * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+ 61526 * @function Chart.helpers.indexOf 61527 * @deprecated since version 2.7.0 61528 * @todo remove at version 3 61529 * @private 61530 */ 61531helpers.indexOf = function(array, item, fromIndex) { 61532 return Array.prototype.indexOf.call(array, item, fromIndex); 61533}; 61534 61535/** 61536 * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead. 61537 * @function Chart.helpers.getValueOrDefault 61538 * @deprecated since version 2.7.0 61539 * @todo remove at version 3 61540 * @private 61541 */ 61542helpers.getValueOrDefault = helpers.valueOrDefault; 61543 61544/** 61545 * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead. 61546 * @function Chart.helpers.getValueAtIndexOrDefault 61547 * @deprecated since version 2.7.0 61548 * @todo remove at version 3 61549 * @private 61550 */ 61551helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault; 61552 61553/** 61554 * Easing functions adapted from Robert Penner's easing equations. 61555 * @namespace Chart.helpers.easingEffects 61556 * @see http://www.robertpenner.com/easing/ 61557 */ 61558var effects = { 61559 linear: function(t) { 61560 return t; 61561 }, 61562 61563 easeInQuad: function(t) { 61564 return t * t; 61565 }, 61566 61567 easeOutQuad: function(t) { 61568 return -t * (t - 2); 61569 }, 61570 61571 easeInOutQuad: function(t) { 61572 if ((t /= 0.5) < 1) { 61573 return 0.5 * t * t; 61574 } 61575 return -0.5 * ((--t) * (t - 2) - 1); 61576 }, 61577 61578 easeInCubic: function(t) { 61579 return t * t * t; 61580 }, 61581 61582 easeOutCubic: function(t) { 61583 return (t = t - 1) * t * t + 1; 61584 }, 61585 61586 easeInOutCubic: function(t) { 61587 if ((t /= 0.5) < 1) { 61588 return 0.5 * t * t * t; 61589 } 61590 return 0.5 * ((t -= 2) * t * t + 2); 61591 }, 61592 61593 easeInQuart: function(t) { 61594 return t * t * t * t; 61595 }, 61596 61597 easeOutQuart: function(t) { 61598 return -((t = t - 1) * t * t * t - 1); 61599 }, 61600 61601 easeInOutQuart: function(t) { 61602 if ((t /= 0.5) < 1) { 61603 return 0.5 * t * t * t * t; 61604 } 61605 return -0.5 * ((t -= 2) * t * t * t - 2); 61606 }, 61607 61608 easeInQuint: function(t) { 61609 return t * t * t * t * t; 61610 }, 61611 61612 easeOutQuint: function(t) { 61613 return (t = t - 1) * t * t * t * t + 1; 61614 }, 61615 61616 easeInOutQuint: function(t) { 61617 if ((t /= 0.5) < 1) { 61618 return 0.5 * t * t * t * t * t; 61619 } 61620 return 0.5 * ((t -= 2) * t * t * t * t + 2); 61621 }, 61622 61623 easeInSine: function(t) { 61624 return -Math.cos(t * (Math.PI / 2)) + 1; 61625 }, 61626 61627 easeOutSine: function(t) { 61628 return Math.sin(t * (Math.PI / 2)); 61629 }, 61630 61631 easeInOutSine: function(t) { 61632 return -0.5 * (Math.cos(Math.PI * t) - 1); 61633 }, 61634 61635 easeInExpo: function(t) { 61636 return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)); 61637 }, 61638 61639 easeOutExpo: function(t) { 61640 return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1; 61641 }, 61642 61643 easeInOutExpo: function(t) { 61644 if (t === 0) { 61645 return 0; 61646 } 61647 if (t === 1) { 61648 return 1; 61649 } 61650 if ((t /= 0.5) < 1) { 61651 return 0.5 * Math.pow(2, 10 * (t - 1)); 61652 } 61653 return 0.5 * (-Math.pow(2, -10 * --t) + 2); 61654 }, 61655 61656 easeInCirc: function(t) { 61657 if (t >= 1) { 61658 return t; 61659 } 61660 return -(Math.sqrt(1 - t * t) - 1); 61661 }, 61662 61663 easeOutCirc: function(t) { 61664 return Math.sqrt(1 - (t = t - 1) * t); 61665 }, 61666 61667 easeInOutCirc: function(t) { 61668 if ((t /= 0.5) < 1) { 61669 return -0.5 * (Math.sqrt(1 - t * t) - 1); 61670 } 61671 return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); 61672 }, 61673 61674 easeInElastic: function(t) { 61675 var s = 1.70158; 61676 var p = 0; 61677 var a = 1; 61678 if (t === 0) { 61679 return 0; 61680 } 61681 if (t === 1) { 61682 return 1; 61683 } 61684 if (!p) { 61685 p = 0.3; 61686 } 61687 if (a < 1) { 61688 a = 1; 61689 s = p / 4; 61690 } else { 61691 s = p / (2 * Math.PI) * Math.asin(1 / a); 61692 } 61693 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); 61694 }, 61695 61696 easeOutElastic: function(t) { 61697 var s = 1.70158; 61698 var p = 0; 61699 var a = 1; 61700 if (t === 0) { 61701 return 0; 61702 } 61703 if (t === 1) { 61704 return 1; 61705 } 61706 if (!p) { 61707 p = 0.3; 61708 } 61709 if (a < 1) { 61710 a = 1; 61711 s = p / 4; 61712 } else { 61713 s = p / (2 * Math.PI) * Math.asin(1 / a); 61714 } 61715 return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1; 61716 }, 61717 61718 easeInOutElastic: function(t) { 61719 var s = 1.70158; 61720 var p = 0; 61721 var a = 1; 61722 if (t === 0) { 61723 return 0; 61724 } 61725 if ((t /= 0.5) === 2) { 61726 return 1; 61727 } 61728 if (!p) { 61729 p = 0.45; 61730 } 61731 if (a < 1) { 61732 a = 1; 61733 s = p / 4; 61734 } else { 61735 s = p / (2 * Math.PI) * Math.asin(1 / a); 61736 } 61737 if (t < 1) { 61738 return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); 61739 } 61740 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1; 61741 }, 61742 easeInBack: function(t) { 61743 var s = 1.70158; 61744 return t * t * ((s + 1) * t - s); 61745 }, 61746 61747 easeOutBack: function(t) { 61748 var s = 1.70158; 61749 return (t = t - 1) * t * ((s + 1) * t + s) + 1; 61750 }, 61751 61752 easeInOutBack: function(t) { 61753 var s = 1.70158; 61754 if ((t /= 0.5) < 1) { 61755 return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); 61756 } 61757 return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); 61758 }, 61759 61760 easeInBounce: function(t) { 61761 return 1 - effects.easeOutBounce(1 - t); 61762 }, 61763 61764 easeOutBounce: function(t) { 61765 if (t < (1 / 2.75)) { 61766 return 7.5625 * t * t; 61767 } 61768 if (t < (2 / 2.75)) { 61769 return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75; 61770 } 61771 if (t < (2.5 / 2.75)) { 61772 return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375; 61773 } 61774 return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375; 61775 }, 61776 61777 easeInOutBounce: function(t) { 61778 if (t < 0.5) { 61779 return effects.easeInBounce(t * 2) * 0.5; 61780 } 61781 return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5; 61782 } 61783}; 61784 61785var helpers_easing = { 61786 effects: effects 61787}; 61788 61789// DEPRECATIONS 61790 61791/** 61792 * Provided for backward compatibility, use Chart.helpers.easing.effects instead. 61793 * @function Chart.helpers.easingEffects 61794 * @deprecated since version 2.7.0 61795 * @todo remove at version 3 61796 * @private 61797 */ 61798helpers_core.easingEffects = effects; 61799 61800var PI = Math.PI; 61801var RAD_PER_DEG = PI / 180; 61802var DOUBLE_PI = PI * 2; 61803var HALF_PI = PI / 2; 61804var QUARTER_PI = PI / 4; 61805var TWO_THIRDS_PI = PI * 2 / 3; 61806 61807/** 61808 * @namespace Chart.helpers.canvas 61809 */ 61810var exports$1 = { 61811 /** 61812 * Clears the entire canvas associated to the given `chart`. 61813 * @param {Chart} chart - The chart for which to clear the canvas. 61814 */ 61815 clear: function(chart) { 61816 chart.ctx.clearRect(0, 0, chart.width, chart.height); 61817 }, 61818 61819 /** 61820 * Creates a "path" for a rectangle with rounded corners at position (x, y) with a 61821 * given size (width, height) and the same `radius` for all corners. 61822 * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context. 61823 * @param {number} x - The x axis of the coordinate for the rectangle starting point. 61824 * @param {number} y - The y axis of the coordinate for the rectangle starting point. 61825 * @param {number} width - The rectangle's width. 61826 * @param {number} height - The rectangle's height. 61827 * @param {number} radius - The rounded amount (in pixels) for the four corners. 61828 * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object? 61829 */ 61830 roundedRect: function(ctx, x, y, width, height, radius) { 61831 if (radius) { 61832 var r = Math.min(radius, height / 2, width / 2); 61833 var left = x + r; 61834 var top = y + r; 61835 var right = x + width - r; 61836 var bottom = y + height - r; 61837 61838 ctx.moveTo(x, top); 61839 if (left < right && top < bottom) { 61840 ctx.arc(left, top, r, -PI, -HALF_PI); 61841 ctx.arc(right, top, r, -HALF_PI, 0); 61842 ctx.arc(right, bottom, r, 0, HALF_PI); 61843 ctx.arc(left, bottom, r, HALF_PI, PI); 61844 } else if (left < right) { 61845 ctx.moveTo(left, y); 61846 ctx.arc(right, top, r, -HALF_PI, HALF_PI); 61847 ctx.arc(left, top, r, HALF_PI, PI + HALF_PI); 61848 } else if (top < bottom) { 61849 ctx.arc(left, top, r, -PI, 0); 61850 ctx.arc(left, bottom, r, 0, PI); 61851 } else { 61852 ctx.arc(left, top, r, -PI, PI); 61853 } 61854 ctx.closePath(); 61855 ctx.moveTo(x, y); 61856 } else { 61857 ctx.rect(x, y, width, height); 61858 } 61859 }, 61860 61861 drawPoint: function(ctx, style, radius, x, y, rotation) { 61862 var type, xOffset, yOffset, size, cornerRadius; 61863 var rad = (rotation || 0) * RAD_PER_DEG; 61864 61865 if (style && typeof style === 'object') { 61866 type = style.toString(); 61867 if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { 61868 ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height); 61869 return; 61870 } 61871 } 61872 61873 if (isNaN(radius) || radius <= 0) { 61874 return; 61875 } 61876 61877 ctx.beginPath(); 61878 61879 switch (style) { 61880 // Default includes circle 61881 default: 61882 ctx.arc(x, y, radius, 0, DOUBLE_PI); 61883 ctx.closePath(); 61884 break; 61885 case 'triangle': 61886 ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); 61887 rad += TWO_THIRDS_PI; 61888 ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); 61889 rad += TWO_THIRDS_PI; 61890 ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); 61891 ctx.closePath(); 61892 break; 61893 case 'rectRounded': 61894 // NOTE: the rounded rect implementation changed to use `arc` instead of 61895 // `quadraticCurveTo` since it generates better results when rect is 61896 // almost a circle. 0.516 (instead of 0.5) produces results with visually 61897 // closer proportion to the previous impl and it is inscribed in the 61898 // circle with `radius`. For more details, see the following PRs: 61899 // https://github.com/chartjs/Chart.js/issues/5597 61900 // https://github.com/chartjs/Chart.js/issues/5858 61901 cornerRadius = radius * 0.516; 61902 size = radius - cornerRadius; 61903 xOffset = Math.cos(rad + QUARTER_PI) * size; 61904 yOffset = Math.sin(rad + QUARTER_PI) * size; 61905 ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI); 61906 ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad); 61907 ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI); 61908 ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI); 61909 ctx.closePath(); 61910 break; 61911 case 'rect': 61912 if (!rotation) { 61913 size = Math.SQRT1_2 * radius; 61914 ctx.rect(x - size, y - size, 2 * size, 2 * size); 61915 break; 61916 } 61917 rad += QUARTER_PI; 61918 /* falls through */ 61919 case 'rectRot': 61920 xOffset = Math.cos(rad) * radius; 61921 yOffset = Math.sin(rad) * radius; 61922 ctx.moveTo(x - xOffset, y - yOffset); 61923 ctx.lineTo(x + yOffset, y - xOffset); 61924 ctx.lineTo(x + xOffset, y + yOffset); 61925 ctx.lineTo(x - yOffset, y + xOffset); 61926 ctx.closePath(); 61927 break; 61928 case 'crossRot': 61929 rad += QUARTER_PI; 61930 /* falls through */ 61931 case 'cross': 61932 xOffset = Math.cos(rad) * radius; 61933 yOffset = Math.sin(rad) * radius; 61934 ctx.moveTo(x - xOffset, y - yOffset); 61935 ctx.lineTo(x + xOffset, y + yOffset); 61936 ctx.moveTo(x + yOffset, y - xOffset); 61937 ctx.lineTo(x - yOffset, y + xOffset); 61938 break; 61939 case 'star': 61940 xOffset = Math.cos(rad) * radius; 61941 yOffset = Math.sin(rad) * radius; 61942 ctx.moveTo(x - xOffset, y - yOffset); 61943 ctx.lineTo(x + xOffset, y + yOffset); 61944 ctx.moveTo(x + yOffset, y - xOffset); 61945 ctx.lineTo(x - yOffset, y + xOffset); 61946 rad += QUARTER_PI; 61947 xOffset = Math.cos(rad) * radius; 61948 yOffset = Math.sin(rad) * radius; 61949 ctx.moveTo(x - xOffset, y - yOffset); 61950 ctx.lineTo(x + xOffset, y + yOffset); 61951 ctx.moveTo(x + yOffset, y - xOffset); 61952 ctx.lineTo(x - yOffset, y + xOffset); 61953 break; 61954 case 'line': 61955 xOffset = Math.cos(rad) * radius; 61956 yOffset = Math.sin(rad) * radius; 61957 ctx.moveTo(x - xOffset, y - yOffset); 61958 ctx.lineTo(x + xOffset, y + yOffset); 61959 break; 61960 case 'dash': 61961 ctx.moveTo(x, y); 61962 ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius); 61963 break; 61964 } 61965 61966 ctx.fill(); 61967 ctx.stroke(); 61968 }, 61969 61970 /** 61971 * Returns true if the point is inside the rectangle 61972 * @param {object} point - The point to test 61973 * @param {object} area - The rectangle 61974 * @returns {boolean} 61975 * @private 61976 */ 61977 _isPointInArea: function(point, area) { 61978 var epsilon = 1e-6; // 1e-6 is margin in pixels for accumulated error. 61979 61980 return point.x > area.left - epsilon && point.x < area.right + epsilon && 61981 point.y > area.top - epsilon && point.y < area.bottom + epsilon; 61982 }, 61983 61984 clipArea: function(ctx, area) { 61985 ctx.save(); 61986 ctx.beginPath(); 61987 ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); 61988 ctx.clip(); 61989 }, 61990 61991 unclipArea: function(ctx) { 61992 ctx.restore(); 61993 }, 61994 61995 lineTo: function(ctx, previous, target, flip) { 61996 var stepped = target.steppedLine; 61997 if (stepped) { 61998 if (stepped === 'middle') { 61999 var midpoint = (previous.x + target.x) / 2.0; 62000 ctx.lineTo(midpoint, flip ? target.y : previous.y); 62001 ctx.lineTo(midpoint, flip ? previous.y : target.y); 62002 } else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) { 62003 ctx.lineTo(previous.x, target.y); 62004 } else { 62005 ctx.lineTo(target.x, previous.y); 62006 } 62007 ctx.lineTo(target.x, target.y); 62008 return; 62009 } 62010 62011 if (!target.tension) { 62012 ctx.lineTo(target.x, target.y); 62013 return; 62014 } 62015 62016 ctx.bezierCurveTo( 62017 flip ? previous.controlPointPreviousX : previous.controlPointNextX, 62018 flip ? previous.controlPointPreviousY : previous.controlPointNextY, 62019 flip ? target.controlPointNextX : target.controlPointPreviousX, 62020 flip ? target.controlPointNextY : target.controlPointPreviousY, 62021 target.x, 62022 target.y); 62023 } 62024}; 62025 62026var helpers_canvas = exports$1; 62027 62028// DEPRECATIONS 62029 62030/** 62031 * Provided for backward compatibility, use Chart.helpers.canvas.clear instead. 62032 * @namespace Chart.helpers.clear 62033 * @deprecated since version 2.7.0 62034 * @todo remove at version 3 62035 * @private 62036 */ 62037helpers_core.clear = exports$1.clear; 62038 62039/** 62040 * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead. 62041 * @namespace Chart.helpers.drawRoundedRectangle 62042 * @deprecated since version 2.7.0 62043 * @todo remove at version 3 62044 * @private 62045 */ 62046helpers_core.drawRoundedRectangle = function(ctx) { 62047 ctx.beginPath(); 62048 exports$1.roundedRect.apply(exports$1, arguments); 62049}; 62050 62051var defaults = { 62052 /** 62053 * @private 62054 */ 62055 _set: function(scope, values) { 62056 return helpers_core.merge(this[scope] || (this[scope] = {}), values); 62057 } 62058}; 62059 62060defaults._set('global', { 62061 defaultColor: 'rgba(0,0,0,0.1)', 62062 defaultFontColor: '#666', 62063 defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", 62064 defaultFontSize: 12, 62065 defaultFontStyle: 'normal', 62066 defaultLineHeight: 1.2, 62067 showLines: true 62068}); 62069 62070var core_defaults = defaults; 62071 62072var valueOrDefault = helpers_core.valueOrDefault; 62073 62074/** 62075 * Converts the given font object into a CSS font string. 62076 * @param {object} font - A font object. 62077 * @return {string} The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font 62078 * @private 62079 */ 62080function toFontString(font) { 62081 if (!font || helpers_core.isNullOrUndef(font.size) || helpers_core.isNullOrUndef(font.family)) { 62082 return null; 62083 } 62084 62085 return (font.style ? font.style + ' ' : '') 62086 + (font.weight ? font.weight + ' ' : '') 62087 + font.size + 'px ' 62088 + font.family; 62089} 62090 62091/** 62092 * @alias Chart.helpers.options 62093 * @namespace 62094 */ 62095var helpers_options = { 62096 /** 62097 * Converts the given line height `value` in pixels for a specific font `size`. 62098 * @param {number|string} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). 62099 * @param {number} size - The font size (in pixels) used to resolve relative `value`. 62100 * @returns {number} The effective line height in pixels (size * 1.2 if value is invalid). 62101 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height 62102 * @since 2.7.0 62103 */ 62104 toLineHeight: function(value, size) { 62105 var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/); 62106 if (!matches || matches[1] === 'normal') { 62107 return size * 1.2; 62108 } 62109 62110 value = +matches[2]; 62111 62112 switch (matches[3]) { 62113 case 'px': 62114 return value; 62115 case '%': 62116 value /= 100; 62117 break; 62118 default: 62119 break; 62120 } 62121 62122 return size * value; 62123 }, 62124 62125 /** 62126 * Converts the given value into a padding object with pre-computed width/height. 62127 * @param {number|object} value - If a number, set the value to all TRBL component, 62128 * else, if and object, use defined properties and sets undefined ones to 0. 62129 * @returns {object} The padding values (top, right, bottom, left, width, height) 62130 * @since 2.7.0 62131 */ 62132 toPadding: function(value) { 62133 var t, r, b, l; 62134 62135 if (helpers_core.isObject(value)) { 62136 t = +value.top || 0; 62137 r = +value.right || 0; 62138 b = +value.bottom || 0; 62139 l = +value.left || 0; 62140 } else { 62141 t = r = b = l = +value || 0; 62142 } 62143 62144 return { 62145 top: t, 62146 right: r, 62147 bottom: b, 62148 left: l, 62149 height: t + b, 62150 width: l + r 62151 }; 62152 }, 62153 62154 /** 62155 * Parses font options and returns the font object. 62156 * @param {object} options - A object that contains font options to be parsed. 62157 * @return {object} The font object. 62158 * @todo Support font.* options and renamed to toFont(). 62159 * @private 62160 */ 62161 _parseFont: function(options) { 62162 var globalDefaults = core_defaults.global; 62163 var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize); 62164 var font = { 62165 family: valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily), 62166 lineHeight: helpers_core.options.toLineHeight(valueOrDefault(options.lineHeight, globalDefaults.defaultLineHeight), size), 62167 size: size, 62168 style: valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle), 62169 weight: null, 62170 string: '' 62171 }; 62172 62173 font.string = toFontString(font); 62174 return font; 62175 }, 62176 62177 /** 62178 * Evaluates the given `inputs` sequentially and returns the first defined value. 62179 * @param {Array} inputs - An array of values, falling back to the last value. 62180 * @param {object} [context] - If defined and the current value is a function, the value 62181 * is called with `context` as first argument and the result becomes the new input. 62182 * @param {number} [index] - If defined and the current value is an array, the value 62183 * at `index` become the new input. 62184 * @since 2.7.0 62185 */ 62186 resolve: function(inputs, context, index) { 62187 var i, ilen, value; 62188 62189 for (i = 0, ilen = inputs.length; i < ilen; ++i) { 62190 value = inputs[i]; 62191 if (value === undefined) { 62192 continue; 62193 } 62194 if (context !== undefined && typeof value === 'function') { 62195 value = value(context); 62196 } 62197 if (index !== undefined && helpers_core.isArray(value)) { 62198 value = value[index]; 62199 } 62200 if (value !== undefined) { 62201 return value; 62202 } 62203 } 62204 } 62205}; 62206 62207var helpers$1 = helpers_core; 62208var easing = helpers_easing; 62209var canvas = helpers_canvas; 62210var options = helpers_options; 62211helpers$1.easing = easing; 62212helpers$1.canvas = canvas; 62213helpers$1.options = options; 62214 62215function interpolate(start, view, model, ease) { 62216 var keys = Object.keys(model); 62217 var i, ilen, key, actual, origin, target, type, c0, c1; 62218 62219 for (i = 0, ilen = keys.length; i < ilen; ++i) { 62220 key = keys[i]; 62221 62222 target = model[key]; 62223 62224 // if a value is added to the model after pivot() has been called, the view 62225 // doesn't contain it, so let's initialize the view to the target value. 62226 if (!view.hasOwnProperty(key)) { 62227 view[key] = target; 62228 } 62229 62230 actual = view[key]; 62231 62232 if (actual === target || key[0] === '_') { 62233 continue; 62234 } 62235 62236 if (!start.hasOwnProperty(key)) { 62237 start[key] = actual; 62238 } 62239 62240 origin = start[key]; 62241 62242 type = typeof target; 62243 62244 if (type === typeof origin) { 62245 if (type === 'string') { 62246 c0 = chartjsColor(origin); 62247 if (c0.valid) { 62248 c1 = chartjsColor(target); 62249 if (c1.valid) { 62250 view[key] = c1.mix(c0, ease).rgbString(); 62251 continue; 62252 } 62253 } 62254 } else if (helpers$1.isFinite(origin) && helpers$1.isFinite(target)) { 62255 view[key] = origin + (target - origin) * ease; 62256 continue; 62257 } 62258 } 62259 62260 view[key] = target; 62261 } 62262} 62263 62264var Element = function(configuration) { 62265 helpers$1.extend(this, configuration); 62266 this.initialize.apply(this, arguments); 62267}; 62268 62269helpers$1.extend(Element.prototype, { 62270 62271 initialize: function() { 62272 this.hidden = false; 62273 }, 62274 62275 pivot: function() { 62276 var me = this; 62277 if (!me._view) { 62278 me._view = helpers$1.clone(me._model); 62279 } 62280 me._start = {}; 62281 return me; 62282 }, 62283 62284 transition: function(ease) { 62285 var me = this; 62286 var model = me._model; 62287 var start = me._start; 62288 var view = me._view; 62289 62290 // No animation -> No Transition 62291 if (!model || ease === 1) { 62292 me._view = model; 62293 me._start = null; 62294 return me; 62295 } 62296 62297 if (!view) { 62298 view = me._view = {}; 62299 } 62300 62301 if (!start) { 62302 start = me._start = {}; 62303 } 62304 62305 interpolate(start, view, model, ease); 62306 62307 return me; 62308 }, 62309 62310 tooltipPosition: function() { 62311 return { 62312 x: this._model.x, 62313 y: this._model.y 62314 }; 62315 }, 62316 62317 hasValue: function() { 62318 return helpers$1.isNumber(this._model.x) && helpers$1.isNumber(this._model.y); 62319 } 62320}); 62321 62322Element.extend = helpers$1.inherits; 62323 62324var core_element = Element; 62325 62326var exports$2 = core_element.extend({ 62327 chart: null, // the animation associated chart instance 62328 currentStep: 0, // the current animation step 62329 numSteps: 60, // default number of steps 62330 easing: '', // the easing to use for this animation 62331 render: null, // render function used by the animation service 62332 62333 onAnimationProgress: null, // user specified callback to fire on each step of the animation 62334 onAnimationComplete: null, // user specified callback to fire when the animation finishes 62335}); 62336 62337var core_animation = exports$2; 62338 62339// DEPRECATIONS 62340 62341/** 62342 * Provided for backward compatibility, use Chart.Animation instead 62343 * @prop Chart.Animation#animationObject 62344 * @deprecated since version 2.6.0 62345 * @todo remove at version 3 62346 */ 62347Object.defineProperty(exports$2.prototype, 'animationObject', { 62348 get: function() { 62349 return this; 62350 } 62351}); 62352 62353/** 62354 * Provided for backward compatibility, use Chart.Animation#chart instead 62355 * @prop Chart.Animation#chartInstance 62356 * @deprecated since version 2.6.0 62357 * @todo remove at version 3 62358 */ 62359Object.defineProperty(exports$2.prototype, 'chartInstance', { 62360 get: function() { 62361 return this.chart; 62362 }, 62363 set: function(value) { 62364 this.chart = value; 62365 } 62366}); 62367 62368core_defaults._set('global', { 62369 animation: { 62370 duration: 1000, 62371 easing: 'easeOutQuart', 62372 onProgress: helpers$1.noop, 62373 onComplete: helpers$1.noop 62374 } 62375}); 62376 62377var core_animations = { 62378 animations: [], 62379 request: null, 62380 62381 /** 62382 * @param {Chart} chart - The chart to animate. 62383 * @param {Chart.Animation} animation - The animation that we will animate. 62384 * @param {number} duration - The animation duration in ms. 62385 * @param {boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions 62386 */ 62387 addAnimation: function(chart, animation, duration, lazy) { 62388 var animations = this.animations; 62389 var i, ilen; 62390 62391 animation.chart = chart; 62392 animation.startTime = Date.now(); 62393 animation.duration = duration; 62394 62395 if (!lazy) { 62396 chart.animating = true; 62397 } 62398 62399 for (i = 0, ilen = animations.length; i < ilen; ++i) { 62400 if (animations[i].chart === chart) { 62401 animations[i] = animation; 62402 return; 62403 } 62404 } 62405 62406 animations.push(animation); 62407 62408 // If there are no animations queued, manually kickstart a digest, for lack of a better word 62409 if (animations.length === 1) { 62410 this.requestAnimationFrame(); 62411 } 62412 }, 62413 62414 cancelAnimation: function(chart) { 62415 var index = helpers$1.findIndex(this.animations, function(animation) { 62416 return animation.chart === chart; 62417 }); 62418 62419 if (index !== -1) { 62420 this.animations.splice(index, 1); 62421 chart.animating = false; 62422 } 62423 }, 62424 62425 requestAnimationFrame: function() { 62426 var me = this; 62427 if (me.request === null) { 62428 // Skip animation frame requests until the active one is executed. 62429 // This can happen when processing mouse events, e.g. 'mousemove' 62430 // and 'mouseout' events will trigger multiple renders. 62431 me.request = helpers$1.requestAnimFrame.call(window, function() { 62432 me.request = null; 62433 me.startDigest(); 62434 }); 62435 } 62436 }, 62437 62438 /** 62439 * @private 62440 */ 62441 startDigest: function() { 62442 var me = this; 62443 62444 me.advance(); 62445 62446 // Do we have more stuff to animate? 62447 if (me.animations.length > 0) { 62448 me.requestAnimationFrame(); 62449 } 62450 }, 62451 62452 /** 62453 * @private 62454 */ 62455 advance: function() { 62456 var animations = this.animations; 62457 var animation, chart, numSteps, nextStep; 62458 var i = 0; 62459 62460 // 1 animation per chart, so we are looping charts here 62461 while (i < animations.length) { 62462 animation = animations[i]; 62463 chart = animation.chart; 62464 numSteps = animation.numSteps; 62465 62466 // Make sure that currentStep starts at 1 62467 // https://github.com/chartjs/Chart.js/issues/6104 62468 nextStep = Math.floor((Date.now() - animation.startTime) / animation.duration * numSteps) + 1; 62469 animation.currentStep = Math.min(nextStep, numSteps); 62470 62471 helpers$1.callback(animation.render, [chart, animation], chart); 62472 helpers$1.callback(animation.onAnimationProgress, [animation], chart); 62473 62474 if (animation.currentStep >= numSteps) { 62475 helpers$1.callback(animation.onAnimationComplete, [animation], chart); 62476 chart.animating = false; 62477 animations.splice(i, 1); 62478 } else { 62479 ++i; 62480 } 62481 } 62482 } 62483}; 62484 62485var resolve = helpers$1.options.resolve; 62486 62487var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; 62488 62489/** 62490 * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', 62491 * 'unshift') and notify the listener AFTER the array has been altered. Listeners are 62492 * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. 62493 */ 62494function listenArrayEvents(array, listener) { 62495 if (array._chartjs) { 62496 array._chartjs.listeners.push(listener); 62497 return; 62498 } 62499 62500 Object.defineProperty(array, '_chartjs', { 62501 configurable: true, 62502 enumerable: false, 62503 value: { 62504 listeners: [listener] 62505 } 62506 }); 62507 62508 arrayEvents.forEach(function(key) { 62509 var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); 62510 var base = array[key]; 62511 62512 Object.defineProperty(array, key, { 62513 configurable: true, 62514 enumerable: false, 62515 value: function() { 62516 var args = Array.prototype.slice.call(arguments); 62517 var res = base.apply(this, args); 62518 62519 helpers$1.each(array._chartjs.listeners, function(object) { 62520 if (typeof object[method] === 'function') { 62521 object[method].apply(object, args); 62522 } 62523 }); 62524 62525 return res; 62526 } 62527 }); 62528 }); 62529} 62530 62531/** 62532 * Removes the given array event listener and cleanup extra attached properties (such as 62533 * the _chartjs stub and overridden methods) if array doesn't have any more listeners. 62534 */ 62535function unlistenArrayEvents(array, listener) { 62536 var stub = array._chartjs; 62537 if (!stub) { 62538 return; 62539 } 62540 62541 var listeners = stub.listeners; 62542 var index = listeners.indexOf(listener); 62543 if (index !== -1) { 62544 listeners.splice(index, 1); 62545 } 62546 62547 if (listeners.length > 0) { 62548 return; 62549 } 62550 62551 arrayEvents.forEach(function(key) { 62552 delete array[key]; 62553 }); 62554 62555 delete array._chartjs; 62556} 62557 62558// Base class for all dataset controllers (line, bar, etc) 62559var DatasetController = function(chart, datasetIndex) { 62560 this.initialize(chart, datasetIndex); 62561}; 62562 62563helpers$1.extend(DatasetController.prototype, { 62564 62565 /** 62566 * Element type used to generate a meta dataset (e.g. Chart.element.Line). 62567 * @type {Chart.core.element} 62568 */ 62569 datasetElementType: null, 62570 62571 /** 62572 * Element type used to generate a meta data (e.g. Chart.element.Point). 62573 * @type {Chart.core.element} 62574 */ 62575 dataElementType: null, 62576 62577 initialize: function(chart, datasetIndex) { 62578 var me = this; 62579 me.chart = chart; 62580 me.index = datasetIndex; 62581 me.linkScales(); 62582 me.addElements(); 62583 }, 62584 62585 updateIndex: function(datasetIndex) { 62586 this.index = datasetIndex; 62587 }, 62588 62589 linkScales: function() { 62590 var me = this; 62591 var meta = me.getMeta(); 62592 var dataset = me.getDataset(); 62593 62594 if (meta.xAxisID === null || !(meta.xAxisID in me.chart.scales)) { 62595 meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id; 62596 } 62597 if (meta.yAxisID === null || !(meta.yAxisID in me.chart.scales)) { 62598 meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id; 62599 } 62600 }, 62601 62602 getDataset: function() { 62603 return this.chart.data.datasets[this.index]; 62604 }, 62605 62606 getMeta: function() { 62607 return this.chart.getDatasetMeta(this.index); 62608 }, 62609 62610 getScaleForId: function(scaleID) { 62611 return this.chart.scales[scaleID]; 62612 }, 62613 62614 /** 62615 * @private 62616 */ 62617 _getValueScaleId: function() { 62618 return this.getMeta().yAxisID; 62619 }, 62620 62621 /** 62622 * @private 62623 */ 62624 _getIndexScaleId: function() { 62625 return this.getMeta().xAxisID; 62626 }, 62627 62628 /** 62629 * @private 62630 */ 62631 _getValueScale: function() { 62632 return this.getScaleForId(this._getValueScaleId()); 62633 }, 62634 62635 /** 62636 * @private 62637 */ 62638 _getIndexScale: function() { 62639 return this.getScaleForId(this._getIndexScaleId()); 62640 }, 62641 62642 reset: function() { 62643 this.update(true); 62644 }, 62645 62646 /** 62647 * @private 62648 */ 62649 destroy: function() { 62650 if (this._data) { 62651 unlistenArrayEvents(this._data, this); 62652 } 62653 }, 62654 62655 createMetaDataset: function() { 62656 var me = this; 62657 var type = me.datasetElementType; 62658 return type && new type({ 62659 _chart: me.chart, 62660 _datasetIndex: me.index 62661 }); 62662 }, 62663 62664 createMetaData: function(index) { 62665 var me = this; 62666 var type = me.dataElementType; 62667 return type && new type({ 62668 _chart: me.chart, 62669 _datasetIndex: me.index, 62670 _index: index 62671 }); 62672 }, 62673 62674 addElements: function() { 62675 var me = this; 62676 var meta = me.getMeta(); 62677 var data = me.getDataset().data || []; 62678 var metaData = meta.data; 62679 var i, ilen; 62680 62681 for (i = 0, ilen = data.length; i < ilen; ++i) { 62682 metaData[i] = metaData[i] || me.createMetaData(i); 62683 } 62684 62685 meta.dataset = meta.dataset || me.createMetaDataset(); 62686 }, 62687 62688 addElementAndReset: function(index) { 62689 var element = this.createMetaData(index); 62690 this.getMeta().data.splice(index, 0, element); 62691 this.updateElement(element, index, true); 62692 }, 62693 62694 buildOrUpdateElements: function() { 62695 var me = this; 62696 var dataset = me.getDataset(); 62697 var data = dataset.data || (dataset.data = []); 62698 62699 // In order to correctly handle data addition/deletion animation (an thus simulate 62700 // real-time charts), we need to monitor these data modifications and synchronize 62701 // the internal meta data accordingly. 62702 if (me._data !== data) { 62703 if (me._data) { 62704 // This case happens when the user replaced the data array instance. 62705 unlistenArrayEvents(me._data, me); 62706 } 62707 62708 if (data && Object.isExtensible(data)) { 62709 listenArrayEvents(data, me); 62710 } 62711 me._data = data; 62712 } 62713 62714 // Re-sync meta data in case the user replaced the data array or if we missed 62715 // any updates and so make sure that we handle number of datapoints changing. 62716 me.resyncElements(); 62717 }, 62718 62719 update: helpers$1.noop, 62720 62721 transition: function(easingValue) { 62722 var meta = this.getMeta(); 62723 var elements = meta.data || []; 62724 var ilen = elements.length; 62725 var i = 0; 62726 62727 for (; i < ilen; ++i) { 62728 elements[i].transition(easingValue); 62729 } 62730 62731 if (meta.dataset) { 62732 meta.dataset.transition(easingValue); 62733 } 62734 }, 62735 62736 draw: function() { 62737 var meta = this.getMeta(); 62738 var elements = meta.data || []; 62739 var ilen = elements.length; 62740 var i = 0; 62741 62742 if (meta.dataset) { 62743 meta.dataset.draw(); 62744 } 62745 62746 for (; i < ilen; ++i) { 62747 elements[i].draw(); 62748 } 62749 }, 62750 62751 removeHoverStyle: function(element) { 62752 helpers$1.merge(element._model, element.$previousStyle || {}); 62753 delete element.$previousStyle; 62754 }, 62755 62756 setHoverStyle: function(element) { 62757 var dataset = this.chart.data.datasets[element._datasetIndex]; 62758 var index = element._index; 62759 var custom = element.custom || {}; 62760 var model = element._model; 62761 var getHoverColor = helpers$1.getHoverColor; 62762 62763 element.$previousStyle = { 62764 backgroundColor: model.backgroundColor, 62765 borderColor: model.borderColor, 62766 borderWidth: model.borderWidth 62767 }; 62768 62769 model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.hoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index); 62770 model.borderColor = resolve([custom.hoverBorderColor, dataset.hoverBorderColor, getHoverColor(model.borderColor)], undefined, index); 62771 model.borderWidth = resolve([custom.hoverBorderWidth, dataset.hoverBorderWidth, model.borderWidth], undefined, index); 62772 }, 62773 62774 /** 62775 * @private 62776 */ 62777 resyncElements: function() { 62778 var me = this; 62779 var meta = me.getMeta(); 62780 var data = me.getDataset().data; 62781 var numMeta = meta.data.length; 62782 var numData = data.length; 62783 62784 if (numData < numMeta) { 62785 meta.data.splice(numData, numMeta - numData); 62786 } else if (numData > numMeta) { 62787 me.insertElements(numMeta, numData - numMeta); 62788 } 62789 }, 62790 62791 /** 62792 * @private 62793 */ 62794 insertElements: function(start, count) { 62795 for (var i = 0; i < count; ++i) { 62796 this.addElementAndReset(start + i); 62797 } 62798 }, 62799 62800 /** 62801 * @private 62802 */ 62803 onDataPush: function() { 62804 var count = arguments.length; 62805 this.insertElements(this.getDataset().data.length - count, count); 62806 }, 62807 62808 /** 62809 * @private 62810 */ 62811 onDataPop: function() { 62812 this.getMeta().data.pop(); 62813 }, 62814 62815 /** 62816 * @private 62817 */ 62818 onDataShift: function() { 62819 this.getMeta().data.shift(); 62820 }, 62821 62822 /** 62823 * @private 62824 */ 62825 onDataSplice: function(start, count) { 62826 this.getMeta().data.splice(start, count); 62827 this.insertElements(start, arguments.length - 2); 62828 }, 62829 62830 /** 62831 * @private 62832 */ 62833 onDataUnshift: function() { 62834 this.insertElements(0, arguments.length); 62835 } 62836}); 62837 62838DatasetController.extend = helpers$1.inherits; 62839 62840var core_datasetController = DatasetController; 62841 62842core_defaults._set('global', { 62843 elements: { 62844 arc: { 62845 backgroundColor: core_defaults.global.defaultColor, 62846 borderColor: '#fff', 62847 borderWidth: 2, 62848 borderAlign: 'center' 62849 } 62850 } 62851}); 62852 62853var element_arc = core_element.extend({ 62854 inLabelRange: function(mouseX) { 62855 var vm = this._view; 62856 62857 if (vm) { 62858 return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); 62859 } 62860 return false; 62861 }, 62862 62863 inRange: function(chartX, chartY) { 62864 var vm = this._view; 62865 62866 if (vm) { 62867 var pointRelativePosition = helpers$1.getAngleFromPoint(vm, {x: chartX, y: chartY}); 62868 var angle = pointRelativePosition.angle; 62869 var distance = pointRelativePosition.distance; 62870 62871 // Sanitise angle range 62872 var startAngle = vm.startAngle; 62873 var endAngle = vm.endAngle; 62874 while (endAngle < startAngle) { 62875 endAngle += 2.0 * Math.PI; 62876 } 62877 while (angle > endAngle) { 62878 angle -= 2.0 * Math.PI; 62879 } 62880 while (angle < startAngle) { 62881 angle += 2.0 * Math.PI; 62882 } 62883 62884 // Check if within the range of the open/close angle 62885 var betweenAngles = (angle >= startAngle && angle <= endAngle); 62886 var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); 62887 62888 return (betweenAngles && withinRadius); 62889 } 62890 return false; 62891 }, 62892 62893 getCenterPoint: function() { 62894 var vm = this._view; 62895 var halfAngle = (vm.startAngle + vm.endAngle) / 2; 62896 var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; 62897 return { 62898 x: vm.x + Math.cos(halfAngle) * halfRadius, 62899 y: vm.y + Math.sin(halfAngle) * halfRadius 62900 }; 62901 }, 62902 62903 getArea: function() { 62904 var vm = this._view; 62905 return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); 62906 }, 62907 62908 tooltipPosition: function() { 62909 var vm = this._view; 62910 var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2); 62911 var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; 62912 62913 return { 62914 x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), 62915 y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) 62916 }; 62917 }, 62918 62919 draw: function() { 62920 var ctx = this._chart.ctx; 62921 var vm = this._view; 62922 var sA = vm.startAngle; 62923 var eA = vm.endAngle; 62924 var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0; 62925 var angleMargin; 62926 62927 ctx.save(); 62928 62929 ctx.beginPath(); 62930 ctx.arc(vm.x, vm.y, Math.max(vm.outerRadius - pixelMargin, 0), sA, eA); 62931 ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); 62932 ctx.closePath(); 62933 62934 ctx.fillStyle = vm.backgroundColor; 62935 ctx.fill(); 62936 62937 if (vm.borderWidth) { 62938 if (vm.borderAlign === 'inner') { 62939 // Draw an inner border by cliping the arc and drawing a double-width border 62940 // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders 62941 ctx.beginPath(); 62942 angleMargin = pixelMargin / vm.outerRadius; 62943 ctx.arc(vm.x, vm.y, vm.outerRadius, sA - angleMargin, eA + angleMargin); 62944 if (vm.innerRadius > pixelMargin) { 62945 angleMargin = pixelMargin / vm.innerRadius; 62946 ctx.arc(vm.x, vm.y, vm.innerRadius - pixelMargin, eA + angleMargin, sA - angleMargin, true); 62947 } else { 62948 ctx.arc(vm.x, vm.y, pixelMargin, eA + Math.PI / 2, sA - Math.PI / 2); 62949 } 62950 ctx.closePath(); 62951 ctx.clip(); 62952 62953 ctx.beginPath(); 62954 ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA); 62955 ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); 62956 ctx.closePath(); 62957 62958 ctx.lineWidth = vm.borderWidth * 2; 62959 ctx.lineJoin = 'round'; 62960 } else { 62961 ctx.lineWidth = vm.borderWidth; 62962 ctx.lineJoin = 'bevel'; 62963 } 62964 62965 ctx.strokeStyle = vm.borderColor; 62966 ctx.stroke(); 62967 } 62968 62969 ctx.restore(); 62970 } 62971}); 62972 62973var valueOrDefault$1 = helpers$1.valueOrDefault; 62974 62975var defaultColor = core_defaults.global.defaultColor; 62976 62977core_defaults._set('global', { 62978 elements: { 62979 line: { 62980 tension: 0.4, 62981 backgroundColor: defaultColor, 62982 borderWidth: 3, 62983 borderColor: defaultColor, 62984 borderCapStyle: 'butt', 62985 borderDash: [], 62986 borderDashOffset: 0.0, 62987 borderJoinStyle: 'miter', 62988 capBezierPoints: true, 62989 fill: true, // do we fill in the area between the line and its base axis 62990 } 62991 } 62992}); 62993 62994var element_line = core_element.extend({ 62995 draw: function() { 62996 var me = this; 62997 var vm = me._view; 62998 var ctx = me._chart.ctx; 62999 var spanGaps = vm.spanGaps; 63000 var points = me._children.slice(); // clone array 63001 var globalDefaults = core_defaults.global; 63002 var globalOptionLineElements = globalDefaults.elements.line; 63003 var lastDrawnIndex = -1; 63004 var index, current, previous, currentVM; 63005 63006 // If we are looping, adding the first point again 63007 if (me._loop && points.length) { 63008 points.push(points[0]); 63009 } 63010 63011 ctx.save(); 63012 63013 // Stroke Line Options 63014 ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; 63015 63016 // IE 9 and 10 do not support line dash 63017 if (ctx.setLineDash) { 63018 ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); 63019 } 63020 63021 ctx.lineDashOffset = valueOrDefault$1(vm.borderDashOffset, globalOptionLineElements.borderDashOffset); 63022 ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; 63023 ctx.lineWidth = valueOrDefault$1(vm.borderWidth, globalOptionLineElements.borderWidth); 63024 ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; 63025 63026 // Stroke Line 63027 ctx.beginPath(); 63028 lastDrawnIndex = -1; 63029 63030 for (index = 0; index < points.length; ++index) { 63031 current = points[index]; 63032 previous = helpers$1.previousItem(points, index); 63033 currentVM = current._view; 63034 63035 // First point moves to it's starting position no matter what 63036 if (index === 0) { 63037 if (!currentVM.skip) { 63038 ctx.moveTo(currentVM.x, currentVM.y); 63039 lastDrawnIndex = index; 63040 } 63041 } else { 63042 previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; 63043 63044 if (!currentVM.skip) { 63045 if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { 63046 // There was a gap and this is the first point after the gap 63047 ctx.moveTo(currentVM.x, currentVM.y); 63048 } else { 63049 // Line to next point 63050 helpers$1.canvas.lineTo(ctx, previous._view, current._view); 63051 } 63052 lastDrawnIndex = index; 63053 } 63054 } 63055 } 63056 63057 ctx.stroke(); 63058 ctx.restore(); 63059 } 63060}); 63061 63062var valueOrDefault$2 = helpers$1.valueOrDefault; 63063 63064var defaultColor$1 = core_defaults.global.defaultColor; 63065 63066core_defaults._set('global', { 63067 elements: { 63068 point: { 63069 radius: 3, 63070 pointStyle: 'circle', 63071 backgroundColor: defaultColor$1, 63072 borderColor: defaultColor$1, 63073 borderWidth: 1, 63074 // Hover 63075 hitRadius: 1, 63076 hoverRadius: 4, 63077 hoverBorderWidth: 1 63078 } 63079 } 63080}); 63081 63082function xRange(mouseX) { 63083 var vm = this._view; 63084 return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false; 63085} 63086 63087function yRange(mouseY) { 63088 var vm = this._view; 63089 return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false; 63090} 63091 63092var element_point = core_element.extend({ 63093 inRange: function(mouseX, mouseY) { 63094 var vm = this._view; 63095 return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; 63096 }, 63097 63098 inLabelRange: xRange, 63099 inXRange: xRange, 63100 inYRange: yRange, 63101 63102 getCenterPoint: function() { 63103 var vm = this._view; 63104 return { 63105 x: vm.x, 63106 y: vm.y 63107 }; 63108 }, 63109 63110 getArea: function() { 63111 return Math.PI * Math.pow(this._view.radius, 2); 63112 }, 63113 63114 tooltipPosition: function() { 63115 var vm = this._view; 63116 return { 63117 x: vm.x, 63118 y: vm.y, 63119 padding: vm.radius + vm.borderWidth 63120 }; 63121 }, 63122 63123 draw: function(chartArea) { 63124 var vm = this._view; 63125 var ctx = this._chart.ctx; 63126 var pointStyle = vm.pointStyle; 63127 var rotation = vm.rotation; 63128 var radius = vm.radius; 63129 var x = vm.x; 63130 var y = vm.y; 63131 var globalDefaults = core_defaults.global; 63132 var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow 63133 63134 if (vm.skip) { 63135 return; 63136 } 63137 63138 // Clipping for Points. 63139 if (chartArea === undefined || helpers$1.canvas._isPointInArea(vm, chartArea)) { 63140 ctx.strokeStyle = vm.borderColor || defaultColor; 63141 ctx.lineWidth = valueOrDefault$2(vm.borderWidth, globalDefaults.elements.point.borderWidth); 63142 ctx.fillStyle = vm.backgroundColor || defaultColor; 63143 helpers$1.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation); 63144 } 63145 } 63146}); 63147 63148var defaultColor$2 = core_defaults.global.defaultColor; 63149 63150core_defaults._set('global', { 63151 elements: { 63152 rectangle: { 63153 backgroundColor: defaultColor$2, 63154 borderColor: defaultColor$2, 63155 borderSkipped: 'bottom', 63156 borderWidth: 0 63157 } 63158 } 63159}); 63160 63161function isVertical(vm) { 63162 return vm && vm.width !== undefined; 63163} 63164 63165/** 63166 * Helper function to get the bounds of the bar regardless of the orientation 63167 * @param bar {Chart.Element.Rectangle} the bar 63168 * @return {Bounds} bounds of the bar 63169 * @private 63170 */ 63171function getBarBounds(vm) { 63172 var x1, x2, y1, y2, half; 63173 63174 if (isVertical(vm)) { 63175 half = vm.width / 2; 63176 x1 = vm.x - half; 63177 x2 = vm.x + half; 63178 y1 = Math.min(vm.y, vm.base); 63179 y2 = Math.max(vm.y, vm.base); 63180 } else { 63181 half = vm.height / 2; 63182 x1 = Math.min(vm.x, vm.base); 63183 x2 = Math.max(vm.x, vm.base); 63184 y1 = vm.y - half; 63185 y2 = vm.y + half; 63186 } 63187 63188 return { 63189 left: x1, 63190 top: y1, 63191 right: x2, 63192 bottom: y2 63193 }; 63194} 63195 63196function swap(orig, v1, v2) { 63197 return orig === v1 ? v2 : orig === v2 ? v1 : orig; 63198} 63199 63200function parseBorderSkipped(vm) { 63201 var edge = vm.borderSkipped; 63202 var res = {}; 63203 63204 if (!edge) { 63205 return res; 63206 } 63207 63208 if (vm.horizontal) { 63209 if (vm.base > vm.x) { 63210 edge = swap(edge, 'left', 'right'); 63211 } 63212 } else if (vm.base < vm.y) { 63213 edge = swap(edge, 'bottom', 'top'); 63214 } 63215 63216 res[edge] = true; 63217 return res; 63218} 63219 63220function parseBorderWidth(vm, maxW, maxH) { 63221 var value = vm.borderWidth; 63222 var skip = parseBorderSkipped(vm); 63223 var t, r, b, l; 63224 63225 if (helpers$1.isObject(value)) { 63226 t = +value.top || 0; 63227 r = +value.right || 0; 63228 b = +value.bottom || 0; 63229 l = +value.left || 0; 63230 } else { 63231 t = r = b = l = +value || 0; 63232 } 63233 63234 return { 63235 t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t, 63236 r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r, 63237 b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b, 63238 l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l 63239 }; 63240} 63241 63242function boundingRects(vm) { 63243 var bounds = getBarBounds(vm); 63244 var width = bounds.right - bounds.left; 63245 var height = bounds.bottom - bounds.top; 63246 var border = parseBorderWidth(vm, width / 2, height / 2); 63247 63248 return { 63249 outer: { 63250 x: bounds.left, 63251 y: bounds.top, 63252 w: width, 63253 h: height 63254 }, 63255 inner: { 63256 x: bounds.left + border.l, 63257 y: bounds.top + border.t, 63258 w: width - border.l - border.r, 63259 h: height - border.t - border.b 63260 } 63261 }; 63262} 63263 63264function inRange(vm, x, y) { 63265 var skipX = x === null; 63266 var skipY = y === null; 63267 var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm); 63268 63269 return bounds 63270 && (skipX || x >= bounds.left && x <= bounds.right) 63271 && (skipY || y >= bounds.top && y <= bounds.bottom); 63272} 63273 63274var element_rectangle = core_element.extend({ 63275 draw: function() { 63276 var ctx = this._chart.ctx; 63277 var vm = this._view; 63278 var rects = boundingRects(vm); 63279 var outer = rects.outer; 63280 var inner = rects.inner; 63281 63282 ctx.fillStyle = vm.backgroundColor; 63283 ctx.fillRect(outer.x, outer.y, outer.w, outer.h); 63284 63285 if (outer.w === inner.w && outer.h === inner.h) { 63286 return; 63287 } 63288 63289 ctx.save(); 63290 ctx.beginPath(); 63291 ctx.rect(outer.x, outer.y, outer.w, outer.h); 63292 ctx.clip(); 63293 ctx.fillStyle = vm.borderColor; 63294 ctx.rect(inner.x, inner.y, inner.w, inner.h); 63295 ctx.fill('evenodd'); 63296 ctx.restore(); 63297 }, 63298 63299 height: function() { 63300 var vm = this._view; 63301 return vm.base - vm.y; 63302 }, 63303 63304 inRange: function(mouseX, mouseY) { 63305 return inRange(this._view, mouseX, mouseY); 63306 }, 63307 63308 inLabelRange: function(mouseX, mouseY) { 63309 var vm = this._view; 63310 return isVertical(vm) 63311 ? inRange(vm, mouseX, null) 63312 : inRange(vm, null, mouseY); 63313 }, 63314 63315 inXRange: function(mouseX) { 63316 return inRange(this._view, mouseX, null); 63317 }, 63318 63319 inYRange: function(mouseY) { 63320 return inRange(this._view, null, mouseY); 63321 }, 63322 63323 getCenterPoint: function() { 63324 var vm = this._view; 63325 var x, y; 63326 if (isVertical(vm)) { 63327 x = vm.x; 63328 y = (vm.y + vm.base) / 2; 63329 } else { 63330 x = (vm.x + vm.base) / 2; 63331 y = vm.y; 63332 } 63333 63334 return {x: x, y: y}; 63335 }, 63336 63337 getArea: function() { 63338 var vm = this._view; 63339 63340 return isVertical(vm) 63341 ? vm.width * Math.abs(vm.y - vm.base) 63342 : vm.height * Math.abs(vm.x - vm.base); 63343 }, 63344 63345 tooltipPosition: function() { 63346 var vm = this._view; 63347 return { 63348 x: vm.x, 63349 y: vm.y 63350 }; 63351 } 63352}); 63353 63354var elements = {}; 63355var Arc = element_arc; 63356var Line = element_line; 63357var Point = element_point; 63358var Rectangle = element_rectangle; 63359elements.Arc = Arc; 63360elements.Line = Line; 63361elements.Point = Point; 63362elements.Rectangle = Rectangle; 63363 63364var resolve$1 = helpers$1.options.resolve; 63365 63366core_defaults._set('bar', { 63367 hover: { 63368 mode: 'label' 63369 }, 63370 63371 scales: { 63372 xAxes: [{ 63373 type: 'category', 63374 categoryPercentage: 0.8, 63375 barPercentage: 0.9, 63376 offset: true, 63377 gridLines: { 63378 offsetGridLines: true 63379 } 63380 }], 63381 63382 yAxes: [{ 63383 type: 'linear' 63384 }] 63385 } 63386}); 63387 63388/** 63389 * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap. 63390 * @private 63391 */ 63392function computeMinSampleSize(scale, pixels) { 63393 var min = scale.isHorizontal() ? scale.width : scale.height; 63394 var ticks = scale.getTicks(); 63395 var prev, curr, i, ilen; 63396 63397 for (i = 1, ilen = pixels.length; i < ilen; ++i) { 63398 min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1])); 63399 } 63400 63401 for (i = 0, ilen = ticks.length; i < ilen; ++i) { 63402 curr = scale.getPixelForTick(i); 63403 min = i > 0 ? Math.min(min, curr - prev) : min; 63404 prev = curr; 63405 } 63406 63407 return min; 63408} 63409 63410/** 63411 * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null, 63412 * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This 63413 * mode currently always generates bars equally sized (until we introduce scriptable options?). 63414 * @private 63415 */ 63416function computeFitCategoryTraits(index, ruler, options) { 63417 var thickness = options.barThickness; 63418 var count = ruler.stackCount; 63419 var curr = ruler.pixels[index]; 63420 var size, ratio; 63421 63422 if (helpers$1.isNullOrUndef(thickness)) { 63423 size = ruler.min * options.categoryPercentage; 63424 ratio = options.barPercentage; 63425 } else { 63426 // When bar thickness is enforced, category and bar percentages are ignored. 63427 // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%') 63428 // and deprecate barPercentage since this value is ignored when thickness is absolute. 63429 size = thickness * count; 63430 ratio = 1; 63431 } 63432 63433 return { 63434 chunk: size / count, 63435 ratio: ratio, 63436 start: curr - (size / 2) 63437 }; 63438} 63439 63440/** 63441 * Computes an "optimal" category that globally arranges bars side by side (no gap when 63442 * percentage options are 1), based on the previous and following categories. This mode 63443 * generates bars with different widths when data are not evenly spaced. 63444 * @private 63445 */ 63446function computeFlexCategoryTraits(index, ruler, options) { 63447 var pixels = ruler.pixels; 63448 var curr = pixels[index]; 63449 var prev = index > 0 ? pixels[index - 1] : null; 63450 var next = index < pixels.length - 1 ? pixels[index + 1] : null; 63451 var percent = options.categoryPercentage; 63452 var start, size; 63453 63454 if (prev === null) { 63455 // first data: its size is double based on the next point or, 63456 // if it's also the last data, we use the scale size. 63457 prev = curr - (next === null ? ruler.end - ruler.start : next - curr); 63458 } 63459 63460 if (next === null) { 63461 // last data: its size is also double based on the previous point. 63462 next = curr + curr - prev; 63463 } 63464 63465 start = curr - (curr - Math.min(prev, next)) / 2 * percent; 63466 size = Math.abs(next - prev) / 2 * percent; 63467 63468 return { 63469 chunk: size / ruler.stackCount, 63470 ratio: options.barPercentage, 63471 start: start 63472 }; 63473} 63474 63475var controller_bar = core_datasetController.extend({ 63476 63477 dataElementType: elements.Rectangle, 63478 63479 initialize: function() { 63480 var me = this; 63481 var meta; 63482 63483 core_datasetController.prototype.initialize.apply(me, arguments); 63484 63485 meta = me.getMeta(); 63486 meta.stack = me.getDataset().stack; 63487 meta.bar = true; 63488 }, 63489 63490 update: function(reset) { 63491 var me = this; 63492 var rects = me.getMeta().data; 63493 var i, ilen; 63494 63495 me._ruler = me.getRuler(); 63496 63497 for (i = 0, ilen = rects.length; i < ilen; ++i) { 63498 me.updateElement(rects[i], i, reset); 63499 } 63500 }, 63501 63502 updateElement: function(rectangle, index, reset) { 63503 var me = this; 63504 var meta = me.getMeta(); 63505 var dataset = me.getDataset(); 63506 var options = me._resolveElementOptions(rectangle, index); 63507 63508 rectangle._xScale = me.getScaleForId(meta.xAxisID); 63509 rectangle._yScale = me.getScaleForId(meta.yAxisID); 63510 rectangle._datasetIndex = me.index; 63511 rectangle._index = index; 63512 rectangle._model = { 63513 backgroundColor: options.backgroundColor, 63514 borderColor: options.borderColor, 63515 borderSkipped: options.borderSkipped, 63516 borderWidth: options.borderWidth, 63517 datasetLabel: dataset.label, 63518 label: me.chart.data.labels[index] 63519 }; 63520 63521 me._updateElementGeometry(rectangle, index, reset); 63522 63523 rectangle.pivot(); 63524 }, 63525 63526 /** 63527 * @private 63528 */ 63529 _updateElementGeometry: function(rectangle, index, reset) { 63530 var me = this; 63531 var model = rectangle._model; 63532 var vscale = me._getValueScale(); 63533 var base = vscale.getBasePixel(); 63534 var horizontal = vscale.isHorizontal(); 63535 var ruler = me._ruler || me.getRuler(); 63536 var vpixels = me.calculateBarValuePixels(me.index, index); 63537 var ipixels = me.calculateBarIndexPixels(me.index, index, ruler); 63538 63539 model.horizontal = horizontal; 63540 model.base = reset ? base : vpixels.base; 63541 model.x = horizontal ? reset ? base : vpixels.head : ipixels.center; 63542 model.y = horizontal ? ipixels.center : reset ? base : vpixels.head; 63543 model.height = horizontal ? ipixels.size : undefined; 63544 model.width = horizontal ? undefined : ipixels.size; 63545 }, 63546 63547 /** 63548 * Returns the stacks based on groups and bar visibility. 63549 * @param {number} [last] - The dataset index 63550 * @returns {string[]} The list of stack IDs 63551 * @private 63552 */ 63553 _getStacks: function(last) { 63554 var me = this; 63555 var chart = me.chart; 63556 var scale = me._getIndexScale(); 63557 var stacked = scale.options.stacked; 63558 var ilen = last === undefined ? chart.data.datasets.length : last + 1; 63559 var stacks = []; 63560 var i, meta; 63561 63562 for (i = 0; i < ilen; ++i) { 63563 meta = chart.getDatasetMeta(i); 63564 if (meta.bar && chart.isDatasetVisible(i) && 63565 (stacked === false || 63566 (stacked === true && stacks.indexOf(meta.stack) === -1) || 63567 (stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) { 63568 stacks.push(meta.stack); 63569 } 63570 } 63571 63572 return stacks; 63573 }, 63574 63575 /** 63576 * Returns the effective number of stacks based on groups and bar visibility. 63577 * @private 63578 */ 63579 getStackCount: function() { 63580 return this._getStacks().length; 63581 }, 63582 63583 /** 63584 * Returns the stack index for the given dataset based on groups and bar visibility. 63585 * @param {number} [datasetIndex] - The dataset index 63586 * @param {string} [name] - The stack name to find 63587 * @returns {number} The stack index 63588 * @private 63589 */ 63590 getStackIndex: function(datasetIndex, name) { 63591 var stacks = this._getStacks(datasetIndex); 63592 var index = (name !== undefined) 63593 ? stacks.indexOf(name) 63594 : -1; // indexOf returns -1 if element is not present 63595 63596 return (index === -1) 63597 ? stacks.length - 1 63598 : index; 63599 }, 63600 63601 /** 63602 * @private 63603 */ 63604 getRuler: function() { 63605 var me = this; 63606 var scale = me._getIndexScale(); 63607 var stackCount = me.getStackCount(); 63608 var datasetIndex = me.index; 63609 var isHorizontal = scale.isHorizontal(); 63610 var start = isHorizontal ? scale.left : scale.top; 63611 var end = start + (isHorizontal ? scale.width : scale.height); 63612 var pixels = []; 63613 var i, ilen, min; 63614 63615 for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { 63616 pixels.push(scale.getPixelForValue(null, i, datasetIndex)); 63617 } 63618 63619 min = helpers$1.isNullOrUndef(scale.options.barThickness) 63620 ? computeMinSampleSize(scale, pixels) 63621 : -1; 63622 63623 return { 63624 min: min, 63625 pixels: pixels, 63626 start: start, 63627 end: end, 63628 stackCount: stackCount, 63629 scale: scale 63630 }; 63631 }, 63632 63633 /** 63634 * Note: pixel values are not clamped to the scale area. 63635 * @private 63636 */ 63637 calculateBarValuePixels: function(datasetIndex, index) { 63638 var me = this; 63639 var chart = me.chart; 63640 var meta = me.getMeta(); 63641 var scale = me._getValueScale(); 63642 var isHorizontal = scale.isHorizontal(); 63643 var datasets = chart.data.datasets; 63644 var value = +scale.getRightValue(datasets[datasetIndex].data[index]); 63645 var minBarLength = scale.options.minBarLength; 63646 var stacked = scale.options.stacked; 63647 var stack = meta.stack; 63648 var start = 0; 63649 var i, imeta, ivalue, base, head, size; 63650 63651 if (stacked || (stacked === undefined && stack !== undefined)) { 63652 for (i = 0; i < datasetIndex; ++i) { 63653 imeta = chart.getDatasetMeta(i); 63654 63655 if (imeta.bar && 63656 imeta.stack === stack && 63657 imeta.controller._getValueScaleId() === scale.id && 63658 chart.isDatasetVisible(i)) { 63659 63660 ivalue = +scale.getRightValue(datasets[i].data[index]); 63661 if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) { 63662 start += ivalue; 63663 } 63664 } 63665 } 63666 } 63667 63668 base = scale.getPixelForValue(start); 63669 head = scale.getPixelForValue(start + value); 63670 size = head - base; 63671 63672 if (minBarLength !== undefined && Math.abs(size) < minBarLength) { 63673 size = minBarLength; 63674 if (value >= 0 && !isHorizontal || value < 0 && isHorizontal) { 63675 head = base - minBarLength; 63676 } else { 63677 head = base + minBarLength; 63678 } 63679 } 63680 63681 return { 63682 size: size, 63683 base: base, 63684 head: head, 63685 center: head + size / 2 63686 }; 63687 }, 63688 63689 /** 63690 * @private 63691 */ 63692 calculateBarIndexPixels: function(datasetIndex, index, ruler) { 63693 var me = this; 63694 var options = ruler.scale.options; 63695 var range = options.barThickness === 'flex' 63696 ? computeFlexCategoryTraits(index, ruler, options) 63697 : computeFitCategoryTraits(index, ruler, options); 63698 63699 var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack); 63700 var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); 63701 var size = Math.min( 63702 helpers$1.valueOrDefault(options.maxBarThickness, Infinity), 63703 range.chunk * range.ratio); 63704 63705 return { 63706 base: center - size / 2, 63707 head: center + size / 2, 63708 center: center, 63709 size: size 63710 }; 63711 }, 63712 63713 draw: function() { 63714 var me = this; 63715 var chart = me.chart; 63716 var scale = me._getValueScale(); 63717 var rects = me.getMeta().data; 63718 var dataset = me.getDataset(); 63719 var ilen = rects.length; 63720 var i = 0; 63721 63722 helpers$1.canvas.clipArea(chart.ctx, chart.chartArea); 63723 63724 for (; i < ilen; ++i) { 63725 if (!isNaN(scale.getRightValue(dataset.data[i]))) { 63726 rects[i].draw(); 63727 } 63728 } 63729 63730 helpers$1.canvas.unclipArea(chart.ctx); 63731 }, 63732 63733 /** 63734 * @private 63735 */ 63736 _resolveElementOptions: function(rectangle, index) { 63737 var me = this; 63738 var chart = me.chart; 63739 var datasets = chart.data.datasets; 63740 var dataset = datasets[me.index]; 63741 var custom = rectangle.custom || {}; 63742 var options = chart.options.elements.rectangle; 63743 var values = {}; 63744 var i, ilen, key; 63745 63746 // Scriptable options 63747 var context = { 63748 chart: chart, 63749 dataIndex: index, 63750 dataset: dataset, 63751 datasetIndex: me.index 63752 }; 63753 63754 var keys = [ 63755 'backgroundColor', 63756 'borderColor', 63757 'borderSkipped', 63758 'borderWidth' 63759 ]; 63760 63761 for (i = 0, ilen = keys.length; i < ilen; ++i) { 63762 key = keys[i]; 63763 values[key] = resolve$1([ 63764 custom[key], 63765 dataset[key], 63766 options[key] 63767 ], context, index); 63768 } 63769 63770 return values; 63771 } 63772}); 63773 63774var valueOrDefault$3 = helpers$1.valueOrDefault; 63775var resolve$2 = helpers$1.options.resolve; 63776 63777core_defaults._set('bubble', { 63778 hover: { 63779 mode: 'single' 63780 }, 63781 63782 scales: { 63783 xAxes: [{ 63784 type: 'linear', // bubble should probably use a linear scale by default 63785 position: 'bottom', 63786 id: 'x-axis-0' // need an ID so datasets can reference the scale 63787 }], 63788 yAxes: [{ 63789 type: 'linear', 63790 position: 'left', 63791 id: 'y-axis-0' 63792 }] 63793 }, 63794 63795 tooltips: { 63796 callbacks: { 63797 title: function() { 63798 // Title doesn't make sense for scatter since we format the data as a point 63799 return ''; 63800 }, 63801 label: function(item, data) { 63802 var datasetLabel = data.datasets[item.datasetIndex].label || ''; 63803 var dataPoint = data.datasets[item.datasetIndex].data[item.index]; 63804 return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')'; 63805 } 63806 } 63807 } 63808}); 63809 63810var controller_bubble = core_datasetController.extend({ 63811 /** 63812 * @protected 63813 */ 63814 dataElementType: elements.Point, 63815 63816 /** 63817 * @protected 63818 */ 63819 update: function(reset) { 63820 var me = this; 63821 var meta = me.getMeta(); 63822 var points = meta.data; 63823 63824 // Update Points 63825 helpers$1.each(points, function(point, index) { 63826 me.updateElement(point, index, reset); 63827 }); 63828 }, 63829 63830 /** 63831 * @protected 63832 */ 63833 updateElement: function(point, index, reset) { 63834 var me = this; 63835 var meta = me.getMeta(); 63836 var custom = point.custom || {}; 63837 var xScale = me.getScaleForId(meta.xAxisID); 63838 var yScale = me.getScaleForId(meta.yAxisID); 63839 var options = me._resolveElementOptions(point, index); 63840 var data = me.getDataset().data[index]; 63841 var dsIndex = me.index; 63842 63843 var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex); 63844 var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex); 63845 63846 point._xScale = xScale; 63847 point._yScale = yScale; 63848 point._options = options; 63849 point._datasetIndex = dsIndex; 63850 point._index = index; 63851 point._model = { 63852 backgroundColor: options.backgroundColor, 63853 borderColor: options.borderColor, 63854 borderWidth: options.borderWidth, 63855 hitRadius: options.hitRadius, 63856 pointStyle: options.pointStyle, 63857 rotation: options.rotation, 63858 radius: reset ? 0 : options.radius, 63859 skip: custom.skip || isNaN(x) || isNaN(y), 63860 x: x, 63861 y: y, 63862 }; 63863 63864 point.pivot(); 63865 }, 63866 63867 /** 63868 * @protected 63869 */ 63870 setHoverStyle: function(point) { 63871 var model = point._model; 63872 var options = point._options; 63873 var getHoverColor = helpers$1.getHoverColor; 63874 63875 point.$previousStyle = { 63876 backgroundColor: model.backgroundColor, 63877 borderColor: model.borderColor, 63878 borderWidth: model.borderWidth, 63879 radius: model.radius 63880 }; 63881 63882 model.backgroundColor = valueOrDefault$3(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); 63883 model.borderColor = valueOrDefault$3(options.hoverBorderColor, getHoverColor(options.borderColor)); 63884 model.borderWidth = valueOrDefault$3(options.hoverBorderWidth, options.borderWidth); 63885 model.radius = options.radius + options.hoverRadius; 63886 }, 63887 63888 /** 63889 * @private 63890 */ 63891 _resolveElementOptions: function(point, index) { 63892 var me = this; 63893 var chart = me.chart; 63894 var datasets = chart.data.datasets; 63895 var dataset = datasets[me.index]; 63896 var custom = point.custom || {}; 63897 var options = chart.options.elements.point; 63898 var data = dataset.data[index]; 63899 var values = {}; 63900 var i, ilen, key; 63901 63902 // Scriptable options 63903 var context = { 63904 chart: chart, 63905 dataIndex: index, 63906 dataset: dataset, 63907 datasetIndex: me.index 63908 }; 63909 63910 var keys = [ 63911 'backgroundColor', 63912 'borderColor', 63913 'borderWidth', 63914 'hoverBackgroundColor', 63915 'hoverBorderColor', 63916 'hoverBorderWidth', 63917 'hoverRadius', 63918 'hitRadius', 63919 'pointStyle', 63920 'rotation' 63921 ]; 63922 63923 for (i = 0, ilen = keys.length; i < ilen; ++i) { 63924 key = keys[i]; 63925 values[key] = resolve$2([ 63926 custom[key], 63927 dataset[key], 63928 options[key] 63929 ], context, index); 63930 } 63931 63932 // Custom radius resolution 63933 values.radius = resolve$2([ 63934 custom.radius, 63935 data ? data.r : undefined, 63936 dataset.radius, 63937 options.radius 63938 ], context, index); 63939 63940 return values; 63941 } 63942}); 63943 63944var resolve$3 = helpers$1.options.resolve; 63945var valueOrDefault$4 = helpers$1.valueOrDefault; 63946 63947core_defaults._set('doughnut', { 63948 animation: { 63949 // Boolean - Whether we animate the rotation of the Doughnut 63950 animateRotate: true, 63951 // Boolean - Whether we animate scaling the Doughnut from the centre 63952 animateScale: false 63953 }, 63954 hover: {
63955 mode: 'single' 63956 }, 63957 legendCallback: function(chart) { 63958 var text = []; 63959 text.push('<ul class="' + chart.id + '-legend">'); 63960 63961 var data = chart.data; 63962 var datasets = data.datasets; 63963 var labels = data.labels; 63964 63965 if (datasets.length) { 63966 for (var i = 0; i < datasets[0].data.length; ++i) { 63967 text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); 63968 if (labels[i]) { 63969 text.push(labels[i]); 63970 } 63971 text.push('</li>'); 63972 } 63973 } 63974 63975 text.push('</ul>'); 63976 return text.join(''); 63977 }, 63978 legend: { 63979 labels: { 63980 generateLabels: function(chart) { 63981 var data = chart.data; 63982 if (data.labels.length && data.datasets.length) { 63983 return data.labels.map(function(label, i) { 63984 var meta = chart.getDatasetMeta(0); 63985 var ds = data.datasets[0]; 63986 var arc = meta.data[i]; 63987 var custom = arc && arc.custom || {}; 63988 var arcOpts = chart.options.elements.arc; 63989 var fill = resolve$3([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i); 63990 var stroke = resolve$3([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i); 63991 var bw = resolve$3([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i); 63992 63993 return { 63994 text: label, 63995 fillStyle: fill, 63996 strokeStyle: stroke, 63997 lineWidth: bw, 63998 hidden: isNaN(ds.data[i]) || meta.data[i].hidden, 63999 64000 // Extra data used for toggling the correct item 64001 index: i 64002 }; 64003 }); 64004 } 64005 return []; 64006 } 64007 }, 64008 64009 onClick: function(e, legendItem) { 64010 var index = legendItem.index; 64011 var chart = this.chart; 64012 var i, ilen, meta; 64013 64014 for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { 64015 meta = chart.getDatasetMeta(i); 64016 // toggle visibility of index if exists 64017 if (meta.data[index]) { 64018 meta.data[index].hidden = !meta.data[index].hidden; 64019 } 64020 } 64021 64022 chart.update(); 64023 } 64024 }, 64025 64026 // The percentage of the chart that we cut out of the middle. 64027 cutoutPercentage: 50, 64028 64029 // The rotation of the chart, where the first data arc begins. 64030 rotation: Math.PI * -0.5, 64031 64032 // The total circumference of the chart. 64033 circumference: Math.PI * 2.0, 64034 64035 // Need to override these to give a nice default 64036 tooltips: { 64037 callbacks: { 64038 title: function() { 64039 return ''; 64040 }, 64041 label: function(tooltipItem, data) { 64042 var dataLabel = data.labels[tooltipItem.index]; 64043 var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; 64044 64045 if (helpers$1.isArray(dataLabel)) { 64046 // show value on first line of multiline label 64047 // need to clone because we are changing the value 64048 dataLabel = dataLabel.slice(); 64049 dataLabel[0] += value; 64050 } else { 64051 dataLabel += value; 64052 } 64053 64054 return dataLabel; 64055 } 64056 } 64057 } 64058}); 64059
64060var controller_doughnut = core_datasetController.extend({ 64061 64062 dataElementType: elements.Arc, 64063 64064 linkScales: helpers$1.noop, 64065 64066 // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly 64067 getRingIndex: function(datasetIndex) { 64068 var ringIndex = 0; 64069 64070 for (var j = 0; j < datasetIndex; ++j) { 64071 if (this.chart.isDatasetVisible(j)) { 64072 ++ringIndex; 64073 } 64074 } 64075 64076 return ringIndex; 64077 }, 64078 64079 update: function(reset) { 64080 var me = this; 64081 var chart = me.chart; 64082 var chartArea = chart.chartArea; 64083 var opts = chart.options; 64084 var availableWidth = chartArea.right - chartArea.left; 64085 var availableHeight = chartArea.bottom - chartArea.top; 64086 var minSize = Math.min(availableWidth, availableHeight); 64087 var offset = {x: 0, y: 0}; 64088 var meta = me.getMeta(); 64089 var arcs = meta.data; 64090 var cutoutPercentage = opts.cutoutPercentage; 64091 var circumference = opts.circumference; 64092 var chartWeight = me._getRingWeight(me.index); 64093 var i, ilen; 64094 64095 // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc 64096 if (circumference < Math.PI * 2.0) { 64097 var startAngle = opts.rotation % (Math.PI * 2.0); 64098 startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0); 64099 var endAngle = startAngle + circumference; 64100 var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)}; 64101 var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)}; 64102 var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle); 64103 var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle); 64104 var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle); 64105 var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle); 64106 var cutout = cutoutPercentage / 100.0; 64107 var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))}; 64108 var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))}; 64109 var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5}; 64110 minSize = Math.min(availableWidth / size.width, availableHeight / size.height); 64111 offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5}; 64112 } 64113 64114 for (i = 0, ilen = arcs.length; i < ilen; ++i) { 64115 arcs[i]._options = me._resolveElementOptions(arcs[i], i); 64116 } 64117 64118 chart.borderWidth = me.getMaxBorderWidth(); 64119 chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0); 64120 chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0); 64121 chart.radiusLength = (chart.outerRadius - chart.innerRadius) / (me._getVisibleDatasetWeightTotal() || 1); 64122 chart.offsetX = offset.x * chart.outerRadius; 64123 chart.offsetY = offset.y * chart.outerRadius; 64124 64125 meta.total = me.calculateTotal(); 64126
vendor: 9,881 bytes, lines 64127-64541
64127 me.outerRadius = chart.outerRadius - chart.radiusLength * me._getRingWeightOffset(me.index); 64128 me.innerRadius = Math.max(me.outerRadius - chart.radiusLength * chartWeight, 0); 64129 64130 for (i = 0, ilen = arcs.length; i < ilen; ++i) { 64131 me.updateElement(arcs[i], i, reset); 64132 } 64133 }, 64134 64135 updateElement: function(arc, index, reset) { 64136 var me = this; 64137 var chart = me.chart; 64138 var chartArea = chart.chartArea; 64139 var opts = chart.options; 64140 var animationOpts = opts.animation; 64141 var centerX = (chartArea.left + chartArea.right) / 2; 64142 var centerY = (chartArea.top + chartArea.bottom) / 2; 64143 var startAngle = opts.rotation; // non reset case handled later 64144 var endAngle = opts.rotation; // non reset case handled later 64145 var dataset = me.getDataset(); 64146 var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)); 64147 var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius; 64148 var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius; 64149 var options = arc._options || {}; 64150 64151 helpers$1.extend(arc, { 64152 // Utility 64153 _datasetIndex: me.index, 64154 _index: index, 64155 64156 // Desired view properties 64157 _model: { 64158 backgroundColor: options.backgroundColor, 64159 borderColor: options.borderColor, 64160 borderWidth: options.borderWidth, 64161 borderAlign: options.borderAlign, 64162 x: centerX + chart.offsetX, 64163 y: centerY + chart.offsetY, 64164 startAngle: startAngle, 64165 endAngle: endAngle, 64166 circumference: circumference, 64167 outerRadius: outerRadius, 64168 innerRadius: innerRadius, 64169 label: helpers$1.valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) 64170 } 64171 }); 64172 64173 var model = arc._model; 64174 64175 // Set correct angles if not resetting 64176 if (!reset || !animationOpts.animateRotate) { 64177 if (index === 0) { 64178 model.startAngle = opts.rotation; 64179 } else { 64180 model.startAngle = me.getMeta().data[index - 1]._model.endAngle; 64181 } 64182 64183 model.endAngle = model.startAngle + model.circumference; 64184 } 64185 64186 arc.pivot(); 64187 }, 64188 64189 calculateTotal: function() { 64190 var dataset = this.getDataset(); 64191 var meta = this.getMeta(); 64192 var total = 0; 64193 var value; 64194 64195 helpers$1.each(meta.data, function(element, index) { 64196 value = dataset.data[index]; 64197 if (!isNaN(value) && !element.hidden) { 64198 total += Math.abs(value); 64199 } 64200 }); 64201 64202 /* if (total === 0) { 64203 total = NaN; 64204 }*/ 64205 64206 return total; 64207 }, 64208 64209 calculateCircumference: function(value) { 64210 var total = this.getMeta().total; 64211 if (total > 0 && !isNaN(value)) { 64212 return (Math.PI * 2.0) * (Math.abs(value) / total); 64213 } 64214 return 0; 64215 }, 64216 64217 // gets the max border or hover width to properly scale pie charts 64218 getMaxBorderWidth: function(arcs) { 64219 var me = this; 64220 var max = 0; 64221 var chart = me.chart; 64222 var i, ilen, meta, arc, controller, options, borderWidth, hoverWidth; 64223 64224 if (!arcs) { 64225 // Find the outmost visible dataset 64226 for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { 64227 if (chart.isDatasetVisible(i)) { 64228 meta = chart.getDatasetMeta(i); 64229 arcs = meta.data; 64230 if (i !== me.index) { 64231 controller = meta.controller; 64232 } 64233 break; 64234 } 64235 } 64236 } 64237 64238 if (!arcs) { 64239 return 0; 64240 } 64241 64242 for (i = 0, ilen = arcs.length; i < ilen; ++i) { 64243 arc = arcs[i]; 64244 options = controller ? controller._resolveElementOptions(arc, i) : arc._options; 64245 if (options.borderAlign !== 'inner') { 64246 borderWidth = options.borderWidth; 64247 hoverWidth = options.hoverBorderWidth; 64248 64249 max = borderWidth > max ? borderWidth : max; 64250 max = hoverWidth > max ? hoverWidth : max; 64251 } 64252 } 64253 return max; 64254 }, 64255 64256 /** 64257 * @protected 64258 */ 64259 setHoverStyle: function(arc) { 64260 var model = arc._model; 64261 var options = arc._options; 64262 var getHoverColor = helpers$1.getHoverColor; 64263 64264 arc.$previousStyle = { 64265 backgroundColor: model.backgroundColor, 64266 borderColor: model.borderColor, 64267 borderWidth: model.borderWidth, 64268 }; 64269 64270 model.backgroundColor = valueOrDefault$4(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); 64271 model.borderColor = valueOrDefault$4(options.hoverBorderColor, getHoverColor(options.borderColor)); 64272 model.borderWidth = valueOrDefault$4(options.hoverBorderWidth, options.borderWidth); 64273 }, 64274 64275 /** 64276 * @private 64277 */ 64278 _resolveElementOptions: function(arc, index) { 64279 var me = this; 64280 var chart = me.chart; 64281 var dataset = me.getDataset(); 64282 var custom = arc.custom || {}; 64283 var options = chart.options.elements.arc; 64284 var values = {}; 64285 var i, ilen, key; 64286 64287 // Scriptable options 64288 var context = { 64289 chart: chart, 64290 dataIndex: index, 64291 dataset: dataset, 64292 datasetIndex: me.index 64293 }; 64294 64295 var keys = [ 64296 'backgroundColor', 64297 'borderColor', 64298 'borderWidth', 64299 'borderAlign', 64300 'hoverBackgroundColor', 64301 'hoverBorderColor', 64302 'hoverBorderWidth', 64303 ]; 64304 64305 for (i = 0, ilen = keys.length; i < ilen; ++i) { 64306 key = keys[i]; 64307 values[key] = resolve$3([ 64308 custom[key], 64309 dataset[key], 64310 options[key] 64311 ], context, index); 64312 } 64313 64314 return values; 64315 }, 64316 64317 /** 64318 * Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly 64319 * @private 64320 */ 64321 _getRingWeightOffset: function(datasetIndex) { 64322 var ringWeightOffset = 0; 64323 64324 for (var i = 0; i < datasetIndex; ++i) { 64325 if (this.chart.isDatasetVisible(i)) { 64326 ringWeightOffset += this._getRingWeight(i); 64327 } 64328 } 64329 64330 return ringWeightOffset; 64331 }, 64332 64333 /** 64334 * @private 64335 */ 64336 _getRingWeight: function(dataSetIndex) { 64337 return Math.max(valueOrDefault$4(this.chart.data.datasets[dataSetIndex].weight, 1), 0); 64338 }, 64339 64340 /** 64341 * Returns the sum of all visibile data set weights. This value can be 0. 64342 * @private 64343 */ 64344 _getVisibleDatasetWeightTotal: function() { 64345 return this._getRingWeightOffset(this.chart.data.datasets.length); 64346 } 64347}); 64348 64349core_defaults._set('horizontalBar', { 64350 hover: { 64351 mode: 'index', 64352 axis: 'y' 64353 }, 64354 64355 scales: { 64356 xAxes: [{ 64357 type: 'linear', 64358 position: 'bottom' 64359 }], 64360 64361 yAxes: [{ 64362 type: 'category', 64363 position: 'left', 64364 categoryPercentage: 0.8, 64365 barPercentage: 0.9, 64366 offset: true, 64367 gridLines: { 64368 offsetGridLines: true 64369 } 64370 }] 64371 }, 64372 64373 elements: { 64374 rectangle: { 64375 borderSkipped: 'left' 64376 } 64377 }, 64378 64379 tooltips: { 64380 mode: 'index', 64381 axis: 'y' 64382 } 64383}); 64384 64385var controller_horizontalBar = controller_bar.extend({ 64386 /** 64387 * @private 64388 */ 64389 _getValueScaleId: function() { 64390 return this.getMeta().xAxisID; 64391 }, 64392 64393 /** 64394 * @private 64395 */ 64396 _getIndexScaleId: function() { 64397 return this.getMeta().yAxisID; 64398 } 64399}); 64400 64401var valueOrDefault$5 = helpers$1.valueOrDefault; 64402var resolve$4 = helpers$1.options.resolve; 64403var isPointInArea = helpers$1.canvas._isPointInArea; 64404 64405core_defaults._set('line', { 64406 showLines: true, 64407 spanGaps: false, 64408 64409 hover: { 64410 mode: 'label' 64411 }, 64412 64413 scales: { 64414 xAxes: [{ 64415 type: 'category', 64416 id: 'x-axis-0' 64417 }], 64418 yAxes: [{ 64419 type: 'linear', 64420 id: 'y-axis-0' 64421 }] 64422 } 64423}); 64424 64425function lineEnabled(dataset, options) { 64426 return valueOrDefault$5(dataset.showLine, options.showLines); 64427} 64428 64429var controller_line = core_datasetController.extend({ 64430 64431 datasetElementType: elements.Line, 64432 64433 dataElementType: elements.Point, 64434 64435 update: function(reset) { 64436 var me = this; 64437 var meta = me.getMeta(); 64438 var line = meta.dataset; 64439 var points = meta.data || []; 64440 var scale = me.getScaleForId(meta.yAxisID); 64441 var dataset = me.getDataset(); 64442 var showLine = lineEnabled(dataset, me.chart.options); 64443 var i, ilen; 64444 64445 // Update Line 64446 if (showLine) { 64447 // Compatibility: If the properties are defined with only the old name, use those values 64448 if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { 64449 dataset.lineTension = dataset.tension; 64450 } 64451 64452 // Utility 64453 line._scale = scale; 64454 line._datasetIndex = me.index; 64455 // Data 64456 line._children = points; 64457 // Model 64458 line._model = me._resolveLineOptions(line); 64459 64460 line.pivot(); 64461 } 64462 64463 // Update Points 64464 for (i = 0, ilen = points.length; i < ilen; ++i) { 64465 me.updateElement(points[i], i, reset); 64466 } 64467 64468 if (showLine && line._model.tension !== 0) { 64469 me.updateBezierControlPoints(); 64470 } 64471 64472 // Now pivot the point for animation 64473 for (i = 0, ilen = points.length; i < ilen; ++i) { 64474 points[i].pivot(); 64475 } 64476 }, 64477 64478 updateElement: function(point, index, reset) { 64479 var me = this; 64480 var meta = me.getMeta(); 64481 var custom = point.custom || {}; 64482 var dataset = me.getDataset(); 64483 var datasetIndex = me.index; 64484 var value = dataset.data[index]; 64485 var yScale = me.getScaleForId(meta.yAxisID); 64486 var xScale = me.getScaleForId(meta.xAxisID); 64487 var lineModel = meta.dataset._model; 64488 var x, y; 64489 64490 var options = me._resolvePointOptions(point, index); 64491 64492 x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex); 64493 y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); 64494 64495 // Utility 64496 point._xScale = xScale; 64497 point._yScale = yScale; 64498 point._options = options; 64499 point._datasetIndex = datasetIndex; 64500 point._index = index; 64501 64502 // Desired view properties 64503 point._model = { 64504 x: x, 64505 y: y, 64506 skip: custom.skip || isNaN(x) || isNaN(y), 64507 // Appearance 64508 radius: options.radius, 64509 pointStyle: options.pointStyle, 64510 rotation: options.rotation, 64511 backgroundColor: options.backgroundColor, 64512 borderColor: options.borderColor, 64513 borderWidth: options.borderWidth, 64514 tension: valueOrDefault$5(custom.tension, lineModel ? lineModel.tension : 0), 64515 steppedLine: lineModel ? lineModel.steppedLine : false, 64516 // Tooltip 64517 hitRadius: options.hitRadius 64518 }; 64519 }, 64520 64521 /** 64522 * @private 64523 */ 64524 _resolvePointOptions: function(element, index) { 64525 var me = this; 64526 var chart = me.chart; 64527 var dataset = chart.data.datasets[me.index]; 64528 var custom = element.custom || {}; 64529 var options = chart.options.elements.point; 64530 var values = {}; 64531 var i, ilen, key; 64532 64533 // Scriptable options 64534 var context = { 64535 chart: chart, 64536 dataIndex: index, 64537 dataset: dataset, 64538 datasetIndex: me.index 64539 }; 64540 64541 var ELEMENT_OPTIONS = {
64542 backgroundColor: 'pointBackgroundColor', 64543 borderColor: 'pointBorderColor', 64544 borderWidth: 'pointBorderWidth', 64545 hitRadius: 'pointHitRadius', 64546 hoverBackgroundColor: 'pointHoverBackgroundColor', 64547 hoverBorderColor: 'pointHoverBorderColor', 64548 hoverBorderWidth: 'pointHoverBorderWidth', 64549 hoverRadius: 'pointHoverRadius', 64550 pointStyle: 'pointStyle', 64551 radius: 'pointRadius', 64552 rotation: 'pointRotation' 64553 }; 64554 var keys = Object.keys(ELEMENT_OPTIONS); 64555 64556 for (i = 0, ilen = keys.length; i < ilen; ++i) { 64557 key = keys[i]; 64558 values[key] = resolve$4([ 64559 custom[key], 64560 dataset[ELEMENT_OPTIONS[key]], 64561 dataset[key], 64562 options[key] 64563 ], context, index); 64564 } 64565 64566 return values; 64567 }, 64568 64569 /** 64570 * @private 64571 */ 64572 _resolveLineOptions: function(element) { 64573 var me = this; 64574 var chart = me.chart; 64575 var dataset = chart.data.datasets[me.index]; 64576 var custom = element.custom || {}; 64577 var options = chart.options; 64578 var elementOptions = options.elements.line; 64579 var values = {}; 64580 var i, ilen, key; 64581 64582 var keys = [ 64583 'backgroundColor', 64584 'borderWidth', 64585 'borderColor', 64586 'borderCapStyle', 64587 'borderDash', 64588 'borderDashOffset', 64589 'borderJoinStyle', 64590 'fill', 64591 'cubicInterpolationMode' 64592 ]; 64593 64594 for (i = 0, ilen = keys.length; i < ilen; ++i) { 64595 key = keys[i]; 64596 values[key] = resolve$4([ 64597 custom[key], 64598 dataset[key], 64599 elementOptions[key] 64600 ]); 64601 } 64602 64603 // The default behavior of lines is to break at null values, according 64604 // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 64605 // This option gives lines the ability to span gaps 64606 values.spanGaps = valueOrDefault$5(dataset.spanGaps, options.spanGaps); 64607 values.tension = valueOrDefault$5(dataset.lineTension, elementOptions.tension); 64608 values.steppedLine = resolve$4([custom.steppedLine, dataset.steppedLine, elementOptions.stepped]); 64609 64610 return values; 64611 }, 64612 64613 calculatePointY: function(value, index, datasetIndex) { 64614 var me = this; 64615 var chart = me.chart; 64616 var meta = me.getMeta(); 64617 var yScale = me.getScaleForId(meta.yAxisID); 64618 var sumPos = 0; 64619 var sumNeg = 0; 64620 var i, ds, dsMeta; 64621 64622 if (yScale.options.stacked) { 64623 for (i = 0; i < datasetIndex; i++) { 64624 ds = chart.data.datasets[i]; 64625 dsMeta = chart.getDatasetMeta(i); 64626 if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { 64627 var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); 64628 if (stackedRightValue < 0) { 64629 sumNeg += stackedRightValue || 0; 64630 } else { 64631 sumPos += stackedRightValue || 0; 64632 } 64633 } 64634 } 64635 64636 var rightValue = Number(yScale.getRightValue(value)); 64637 if (rightValue < 0) { 64638 return yScale.getPixelForValue(sumNeg + rightValue); 64639 } 64640 return yScale.getPixelForValue(sumPos + rightValue); 64641 } 64642 64643 return yScale.getPixelForValue(value); 64644 }, 64645 64646 updateBezierControlPoints: function() { 64647 var me = this; 64648 var chart = me.chart; 64649 var meta = me.getMeta(); 64650 var lineModel = meta.dataset._model; 64651 var area = chart.chartArea; 64652 var points = meta.data || []; 64653 var i, ilen, model, controlPoints; 64654 64655 // Only consider points that are drawn in case the spanGaps option is used 64656 if (lineModel.spanGaps) { 64657 points = points.filter(function(pt) { 64658 return !pt._model.skip; 64659 }); 64660 } 64661 64662 function capControlPoint(pt, min, max) { 64663 return Math.max(Math.min(pt, max), min); 64664 } 64665 64666 if (lineModel.cubicInterpolationMode === 'monotone') { 64667 helpers$1.splineCurveMonotone(points); 64668 } else { 64669 for (i = 0, ilen = points.length; i < ilen; ++i) { 64670 model = points[i]._model; 64671 controlPoints = helpers$1.splineCurve( 64672 helpers$1.previousItem(points, i)._model, 64673 model, 64674 helpers$1.nextItem(points, i)._model, 64675 lineModel.tension 64676 ); 64677 model.controlPointPreviousX = controlPoints.previous.x; 64678 model.controlPointPreviousY = controlPoints.previous.y; 64679 model.controlPointNextX = controlPoints.next.x; 64680 model.controlPointNextY = controlPoints.next.y; 64681 } 64682 } 64683 64684 if (chart.options.elements.line.capBezierPoints) { 64685 for (i = 0, ilen = points.length; i < ilen; ++i) { 64686 model = points[i]._model; 64687 if (isPointInArea(model, area)) { 64688 if (i > 0 && isPointInArea(points[i - 1]._model, area)) { 64689 model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); 64690 model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); 64691 } 64692 if (i < points.length - 1 && isPointInArea(points[i + 1]._model, area)) { 64693 model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); 64694 model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); 64695 } 64696 } 64697 } 64698 } 64699 }, 64700 64701 draw: function() { 64702 var me = this; 64703 var chart = me.chart; 64704 var meta = me.getMeta(); 64705 var points = meta.data || []; 64706 var area = chart.chartArea; 64707 var ilen = points.length; 64708 var halfBorderWidth; 64709 var i = 0; 64710 64711 if (lineEnabled(me.getDataset(), chart.options)) { 64712 halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2; 64713 64714 helpers$1.canvas.clipArea(chart.ctx, { 64715 left: area.left, 64716 right: area.right, 64717 top: area.top - halfBorderWidth, 64718 bottom: area.bottom + halfBorderWidth 64719 }); 64720 64721 meta.dataset.draw(); 64722 64723 helpers$1.canvas.unclipArea(chart.ctx); 64724 } 64725 64726 // Draw the points 64727 for (; i < ilen; ++i) { 64728 points[i].draw(area); 64729 } 64730 }, 64731 64732 /** 64733 * @protected 64734 */
64735 setHoverStyle: function(point) { 64736 var model = point._model; 64737 var options = point._options; 64738 var getHoverColor = helpers$1.getHoverColor; 64739 64740 point.$previousStyle = { 64741 backgroundColor: model.backgroundColor, 64742 borderColor: model.borderColor, 64743 borderWidth: model.borderWidth, 64744 radius: model.radius 64745 }; 64746 64747 model.backgroundColor = valueOrDefault$5(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); 64748 model.borderColor = valueOrDefault$5(options.hoverBorderColor, getHoverColor(options.borderColor)); 64749 model.borderWidth = valueOrDefault$5(options.hoverBorderWidth, options.borderWidth); 64750 model.radius = valueOrDefault$5(options.hoverRadius, options.radius); 64751 }, 64752}); 64753 64754var resolve$5 = helpers$1.options.resolve; 64755 64756core_defaults._set('polarArea', { 64757 scale: { 64758 type: 'radialLinear', 64759 angleLines: { 64760 display: false 64761 }, 64762 gridLines: { 64763 circular: true 64764 }, 64765 pointLabels: { 64766 display: false 64767 }, 64768 ticks: { 64769 beginAtZero: true 64770 } 64771 }, 64772 64773 // Boolean - Whether to animate the rotation of the chart 64774 animation: { 64775 animateRotate: true, 64776 animateScale: true 64777 }, 64778 64779 startAngle: -0.5 * Math.PI, 64780 legendCallback: function(chart) { 64781 var text = []; 64782 text.push('<ul class="' + chart.id + '-legend">'); 64783 64784 var data = chart.data; 64785 var datasets = data.datasets; 64786 var labels = data.labels; 64787 64788 if (datasets.length) { 64789 for (var i = 0; i < datasets[0].data.length; ++i) { 64790 text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); 64791 if (labels[i]) { 64792 text.push(labels[i]); 64793 } 64794 text.push('</li>'); 64795 } 64796 } 64797 64798 text.push('</ul>'); 64799 return text.join(''); 64800 }, 64801 legend: { 64802 labels: { 64803 generateLabels: function(chart) { 64804 var data = chart.data; 64805 if (data.labels.length && data.datasets.length) { 64806 return data.labels.map(function(label, i) { 64807 var meta = chart.getDatasetMeta(0); 64808 var ds = data.datasets[0]; 64809 var arc = meta.data[i]; 64810 var custom = arc.custom || {}; 64811 var arcOpts = chart.options.elements.arc; 64812 var fill = resolve$5([custom.backgroundColor, ds.backgroundColor, arcOpts.backgroundColor], undefined, i); 64813 var stroke = resolve$5([custom.borderColor, ds.borderColor, arcOpts.borderColor], undefined, i); 64814 var bw = resolve$5([custom.borderWidth, ds.borderWidth, arcOpts.borderWidth], undefined, i); 64815 64816 return { 64817 text: label, 64818 fillStyle: fill, 64819 strokeStyle: stroke, 64820 lineWidth: bw, 64821 hidden: isNaN(ds.data[i]) || meta.data[i].hidden, 64822 64823 // Extra data used for toggling the correct item 64824 index: i 64825 }; 64826 }); 64827 } 64828 return []; 64829 } 64830 }, 64831 64832 onClick: function(e, legendItem) { 64833 var index = legendItem.index; 64834 var chart = this.chart; 64835 var i, ilen, meta; 64836 64837 for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { 64838 meta = chart.getDatasetMeta(i); 64839 meta.data[index].hidden = !meta.data[index].hidden; 64840 } 64841 64842 chart.update(); 64843 } 64844 }, 64845 64846 // Need to override these to give a nice default 64847 tooltips: { 64848 callbacks: { 64849 title: function() { 64850 return ''; 64851 }, 64852 label: function(item, data) { 64853 return data.labels[item.index] + ': ' + item.yLabel; 64854 } 64855 } 64856 } 64857}); 64858
vendor: 20,646 bytes, lines 64859-65598
64859var controller_polarArea = core_datasetController.extend({ 64860 64861 dataElementType: elements.Arc, 64862 64863 linkScales: helpers$1.noop, 64864 64865 update: function(reset) { 64866 var me = this; 64867 var dataset = me.getDataset(); 64868 var meta = me.getMeta(); 64869 var start = me.chart.options.startAngle || 0; 64870 var starts = me._starts = []; 64871 var angles = me._angles = []; 64872 var arcs = meta.data; 64873 var i, ilen, angle; 64874 64875 me._updateRadius(); 64876 64877 meta.count = me.countVisibleElements(); 64878 64879 for (i = 0, ilen = dataset.data.length; i < ilen; i++) { 64880 starts[i] = start; 64881 angle = me._computeAngle(i); 64882 angles[i] = angle; 64883 start += angle; 64884 } 64885 64886 for (i = 0, ilen = arcs.length; i < ilen; ++i) { 64887 arcs[i]._options = me._resolveElementOptions(arcs[i], i); 64888 me.updateElement(arcs[i], i, reset); 64889 } 64890 }, 64891 64892 /** 64893 * @private 64894 */ 64895 _updateRadius: function() { 64896 var me = this; 64897 var chart = me.chart; 64898 var chartArea = chart.chartArea; 64899 var opts = chart.options; 64900 var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); 64901 64902 chart.outerRadius = Math.max(minSize / 2, 0); 64903 chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); 64904 chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); 64905 64906 me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); 64907 me.innerRadius = me.outerRadius - chart.radiusLength; 64908 }, 64909 64910 updateElement: function(arc, index, reset) { 64911 var me = this; 64912 var chart = me.chart; 64913 var dataset = me.getDataset(); 64914 var opts = chart.options; 64915 var animationOpts = opts.animation; 64916 var scale = chart.scale; 64917 var labels = chart.data.labels; 64918 64919 var centerX = scale.xCenter; 64920 var centerY = scale.yCenter; 64921 64922 // var negHalfPI = -0.5 * Math.PI; 64923 var datasetStartAngle = opts.startAngle; 64924 var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); 64925 var startAngle = me._starts[index]; 64926 var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]); 64927 64928 var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); 64929 var options = arc._options || {}; 64930 64931 helpers$1.extend(arc, { 64932 // Utility 64933 _datasetIndex: me.index, 64934 _index: index, 64935 _scale: scale, 64936 64937 // Desired view properties 64938 _model: { 64939 backgroundColor: options.backgroundColor, 64940 borderColor: options.borderColor, 64941 borderWidth: options.borderWidth, 64942 borderAlign: options.borderAlign, 64943 x: centerX, 64944 y: centerY, 64945 innerRadius: 0, 64946 outerRadius: reset ? resetRadius : distance, 64947 startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, 64948 endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, 64949 label: helpers$1.valueAtIndexOrDefault(labels, index, labels[index]) 64950 } 64951 }); 64952 64953 arc.pivot(); 64954 }, 64955 64956 countVisibleElements: function() { 64957 var dataset = this.getDataset(); 64958 var meta = this.getMeta(); 64959 var count = 0; 64960 64961 helpers$1.each(meta.data, function(element, index) { 64962 if (!isNaN(dataset.data[index]) && !element.hidden) { 64963 count++; 64964 } 64965 }); 64966 64967 return count; 64968 }, 64969 64970 /** 64971 * @protected 64972 */ 64973 setHoverStyle: function(arc) { 64974 var model = arc._model; 64975 var options = arc._options; 64976 var getHoverColor = helpers$1.getHoverColor; 64977 var valueOrDefault = helpers$1.valueOrDefault; 64978 64979 arc.$previousStyle = { 64980 backgroundColor: model.backgroundColor, 64981 borderColor: model.borderColor, 64982 borderWidth: model.borderWidth, 64983 }; 64984 64985 model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); 64986 model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor)); 64987 model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth); 64988 }, 64989 64990 /** 64991 * @private 64992 */ 64993 _resolveElementOptions: function(arc, index) { 64994 var me = this; 64995 var chart = me.chart; 64996 var dataset = me.getDataset(); 64997 var custom = arc.custom || {}; 64998 var options = chart.options.elements.arc; 64999 var values = {}; 65000 var i, ilen, key; 65001 65002 // Scriptable options 65003 var context = { 65004 chart: chart, 65005 dataIndex: index, 65006 dataset: dataset, 65007 datasetIndex: me.index 65008 }; 65009 65010 var keys = [ 65011 'backgroundColor', 65012 'borderColor', 65013 'borderWidth', 65014 'borderAlign', 65015 'hoverBackgroundColor', 65016 'hoverBorderColor', 65017 'hoverBorderWidth', 65018 ]; 65019 65020 for (i = 0, ilen = keys.length; i < ilen; ++i) { 65021 key = keys[i]; 65022 values[key] = resolve$5([ 65023 custom[key], 65024 dataset[key], 65025 options[key] 65026 ], context, index); 65027 } 65028 65029 return values; 65030 }, 65031 65032 /** 65033 * @private 65034 */ 65035 _computeAngle: function(index) { 65036 var me = this; 65037 var count = this.getMeta().count; 65038 var dataset = me.getDataset(); 65039 var meta = me.getMeta(); 65040 65041 if (isNaN(dataset.data[index]) || meta.data[index].hidden) { 65042 return 0; 65043 } 65044 65045 // Scriptable options 65046 var context = { 65047 chart: me.chart, 65048 dataIndex: index, 65049 dataset: dataset, 65050 datasetIndex: me.index 65051 }; 65052 65053 return resolve$5([ 65054 me.chart.options.elements.arc.angle, 65055 (2 * Math.PI) / count 65056 ], context, index); 65057 } 65058}); 65059 65060core_defaults._set('pie', helpers$1.clone(core_defaults.doughnut)); 65061core_defaults._set('pie', { 65062 cutoutPercentage: 0 65063}); 65064 65065// Pie charts are Doughnut chart with different defaults 65066var controller_pie = controller_doughnut; 65067 65068var valueOrDefault$6 = helpers$1.valueOrDefault; 65069var resolve$6 = helpers$1.options.resolve; 65070 65071core_defaults._set('radar', { 65072 scale: { 65073 type: 'radialLinear' 65074 }, 65075 elements: { 65076 line: { 65077 tension: 0 // no bezier in radar 65078 } 65079 } 65080}); 65081 65082var controller_radar = core_datasetController.extend({ 65083 65084 datasetElementType: elements.Line, 65085 65086 dataElementType: elements.Point, 65087 65088 linkScales: helpers$1.noop, 65089 65090 update: function(reset) { 65091 var me = this; 65092 var meta = me.getMeta(); 65093 var line = meta.dataset; 65094 var points = meta.data || []; 65095 var scale = me.chart.scale; 65096 var dataset = me.getDataset(); 65097 var i, ilen; 65098 65099 // Compatibility: If the properties are defined with only the old name, use those values 65100 if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { 65101 dataset.lineTension = dataset.tension; 65102 } 65103 65104 // Utility 65105 line._scale = scale; 65106 line._datasetIndex = me.index; 65107 // Data 65108 line._children = points; 65109 line._loop = true; 65110 // Model 65111 line._model = me._resolveLineOptions(line); 65112 65113 line.pivot(); 65114 65115 // Update Points 65116 for (i = 0, ilen = points.length; i < ilen; ++i) { 65117 me.updateElement(points[i], i, reset); 65118 } 65119 65120 // Update bezier control points 65121 me.updateBezierControlPoints(); 65122 65123 // Now pivot the point for animation 65124 for (i = 0, ilen = points.length; i < ilen; ++i) { 65125 points[i].pivot(); 65126 } 65127 }, 65128 65129 updateElement: function(point, index, reset) { 65130 var me = this; 65131 var custom = point.custom || {}; 65132 var dataset = me.getDataset(); 65133 var scale = me.chart.scale; 65134 var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); 65135 var options = me._resolvePointOptions(point, index); 65136 var lineModel = me.getMeta().dataset._model; 65137 var x = reset ? scale.xCenter : pointPosition.x; 65138 var y = reset ? scale.yCenter : pointPosition.y; 65139 65140 // Utility 65141 point._scale = scale; 65142 point._options = options; 65143 point._datasetIndex = me.index; 65144 point._index = index; 65145 65146 // Desired view properties 65147 point._model = { 65148 x: x, // value not used in dataset scale, but we want a consistent API between scales 65149 y: y, 65150 skip: custom.skip || isNaN(x) || isNaN(y), 65151 // Appearance 65152 radius: options.radius, 65153 pointStyle: options.pointStyle, 65154 rotation: options.rotation, 65155 backgroundColor: options.backgroundColor, 65156 borderColor: options.borderColor, 65157 borderWidth: options.borderWidth, 65158 tension: valueOrDefault$6(custom.tension, lineModel ? lineModel.tension : 0), 65159 65160 // Tooltip 65161 hitRadius: options.hitRadius 65162 }; 65163 }, 65164 65165 /** 65166 * @private 65167 */ 65168 _resolvePointOptions: function(element, index) { 65169 var me = this; 65170 var chart = me.chart; 65171 var dataset = chart.data.datasets[me.index]; 65172 var custom = element.custom || {}; 65173 var options = chart.options.elements.point; 65174 var values = {}; 65175 var i, ilen, key; 65176 65177 // Scriptable options 65178 var context = { 65179 chart: chart, 65180 dataIndex: index, 65181 dataset: dataset, 65182 datasetIndex: me.index 65183 }; 65184 65185 var ELEMENT_OPTIONS = { 65186 backgroundColor: 'pointBackgroundColor', 65187 borderColor: 'pointBorderColor', 65188 borderWidth: 'pointBorderWidth', 65189 hitRadius: 'pointHitRadius', 65190 hoverBackgroundColor: 'pointHoverBackgroundColor', 65191 hoverBorderColor: 'pointHoverBorderColor', 65192 hoverBorderWidth: 'pointHoverBorderWidth', 65193 hoverRadius: 'pointHoverRadius', 65194 pointStyle: 'pointStyle', 65195 radius: 'pointRadius', 65196 rotation: 'pointRotation' 65197 }; 65198 var keys = Object.keys(ELEMENT_OPTIONS); 65199 65200 for (i = 0, ilen = keys.length; i < ilen; ++i) { 65201 key = keys[i]; 65202 values[key] = resolve$6([ 65203 custom[key], 65204 dataset[ELEMENT_OPTIONS[key]], 65205 dataset[key], 65206 options[key] 65207 ], context, index); 65208 } 65209 65210 return values; 65211 }, 65212 65213 /** 65214 * @private 65215 */ 65216 _resolveLineOptions: function(element) { 65217 var me = this; 65218 var chart = me.chart; 65219 var dataset = chart.data.datasets[me.index]; 65220 var custom = element.custom || {}; 65221 var options = chart.options.elements.line; 65222 var values = {}; 65223 var i, ilen, key; 65224 65225 var keys = [ 65226 'backgroundColor', 65227 'borderWidth', 65228 'borderColor', 65229 'borderCapStyle', 65230 'borderDash', 65231 'borderDashOffset', 65232 'borderJoinStyle', 65233 'fill' 65234 ]; 65235 65236 for (i = 0, ilen = keys.length; i < ilen; ++i) { 65237 key = keys[i]; 65238 values[key] = resolve$6([ 65239 custom[key], 65240 dataset[key], 65241 options[key] 65242 ]); 65243 } 65244 65245 values.tension = valueOrDefault$6(dataset.lineTension, options.tension); 65246 65247 return values; 65248 }, 65249 65250 updateBezierControlPoints: function() { 65251 var me = this; 65252 var meta = me.getMeta(); 65253 var area = me.chart.chartArea; 65254 var points = meta.data || []; 65255 var i, ilen, model, controlPoints; 65256 65257 function capControlPoint(pt, min, max) { 65258 return Math.max(Math.min(pt, max), min); 65259 } 65260 65261 for (i = 0, ilen = points.length; i < ilen; ++i) { 65262 model = points[i]._model; 65263 controlPoints = helpers$1.splineCurve( 65264 helpers$1.previousItem(points, i, true)._model, 65265 model, 65266 helpers$1.nextItem(points, i, true)._model, 65267 model.tension 65268 ); 65269 65270 // Prevent the bezier going outside of the bounds of the graph 65271 model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right); 65272 model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom); 65273 model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right); 65274 model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom); 65275 } 65276 }, 65277 65278 setHoverStyle: function(point) { 65279 var model = point._model; 65280 var options = point._options; 65281 var getHoverColor = helpers$1.getHoverColor; 65282 65283 point.$previousStyle = { 65284 backgroundColor: model.backgroundColor, 65285 borderColor: model.borderColor, 65286 borderWidth: model.borderWidth, 65287 radius: model.radius 65288 }; 65289 65290 model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); 65291 model.borderColor = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor)); 65292 model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth); 65293 model.radius = valueOrDefault$6(options.hoverRadius, options.radius); 65294 } 65295}); 65296 65297core_defaults._set('scatter', { 65298 hover: { 65299 mode: 'single' 65300 }, 65301 65302 scales: { 65303 xAxes: [{ 65304 id: 'x-axis-1', // need an ID so datasets can reference the scale 65305 type: 'linear', // scatter should not use a category axis 65306 position: 'bottom' 65307 }], 65308 yAxes: [{ 65309 id: 'y-axis-1', 65310 type: 'linear', 65311 position: 'left' 65312 }] 65313 }, 65314 65315 showLines: false, 65316 65317 tooltips: { 65318 callbacks: { 65319 title: function() { 65320 return ''; // doesn't make sense for scatter since data are formatted as a point 65321 }, 65322 label: function(item) { 65323 return '(' + item.xLabel + ', ' + item.yLabel + ')'; 65324 } 65325 } 65326 } 65327}); 65328 65329// Scatter charts use line controllers 65330var controller_scatter = controller_line; 65331 65332// NOTE export a map in which the key represents the controller type, not 65333// the class, and so must be CamelCase in order to be correctly retrieved 65334// by the controller in core.controller.js (`controllers[meta.type]`). 65335 65336var controllers = { 65337 bar: controller_bar, 65338 bubble: controller_bubble, 65339 doughnut: controller_doughnut, 65340 horizontalBar: controller_horizontalBar, 65341 line: controller_line, 65342 polarArea: controller_polarArea, 65343 pie: controller_pie, 65344 radar: controller_radar, 65345 scatter: controller_scatter 65346}; 65347 65348/** 65349 * Helper function to get relative position for an event 65350 * @param {Event|IEvent} event - The event to get the position for 65351 * @param {Chart} chart - The chart 65352 * @returns {object} the event position 65353 */ 65354function getRelativePosition(e, chart) { 65355 if (e.native) { 65356 return { 65357 x: e.x, 65358 y: e.y 65359 }; 65360 } 65361 65362 return helpers$1.getRelativePosition(e, chart); 65363} 65364 65365/** 65366 * Helper function to traverse all of the visible elements in the chart 65367 * @param {Chart} chart - the chart 65368 * @param {function} handler - the callback to execute for each visible item 65369 */ 65370function parseVisibleItems(chart, handler) { 65371 var datasets = chart.data.datasets; 65372 var meta, i, j, ilen, jlen; 65373 65374 for (i = 0, ilen = datasets.length; i < ilen; ++i) { 65375 if (!chart.isDatasetVisible(i)) { 65376 continue; 65377 } 65378 65379 meta = chart.getDatasetMeta(i); 65380 for (j = 0, jlen = meta.data.length; j < jlen; ++j) { 65381 var element = meta.data[j]; 65382 if (!element._view.skip) { 65383 handler(element); 65384 } 65385 } 65386 } 65387} 65388 65389/** 65390 * Helper function to get the items that intersect the event position 65391 * @param {ChartElement[]} items - elements to filter 65392 * @param {object} position - the point to be nearest to 65393 * @return {ChartElement[]} the nearest items 65394 */ 65395function getIntersectItems(chart, position) { 65396 var elements = []; 65397 65398 parseVisibleItems(chart, function(element) { 65399 if (element.inRange(position.x, position.y)) { 65400 elements.push(element); 65401 } 65402 }); 65403 65404 return elements; 65405} 65406 65407/** 65408 * Helper function to get the items nearest to the event position considering all visible items in teh chart 65409 * @param {Chart} chart - the chart to look at elements from 65410 * @param {object} position - the point to be nearest to 65411 * @param {boolean} intersect - if true, only consider items that intersect the position 65412 * @param {function} distanceMetric - function to provide the distance between points 65413 * @return {ChartElement[]} the nearest items 65414 */ 65415function getNearestItems(chart, position, intersect, distanceMetric) { 65416 var minDistance = Number.POSITIVE_INFINITY; 65417 var nearestItems = []; 65418 65419 parseVisibleItems(chart, function(element) { 65420 if (intersect && !element.inRange(position.x, position.y)) { 65421 return; 65422 } 65423 65424 var center = element.getCenterPoint(); 65425 var distance = distanceMetric(position, center); 65426 if (distance < minDistance) { 65427 nearestItems = [element]; 65428 minDistance = distance; 65429 } else if (distance === minDistance) { 65430 // Can have multiple items at the same distance in which case we sort by size 65431 nearestItems.push(element); 65432 } 65433 }); 65434 65435 return nearestItems; 65436} 65437 65438/** 65439 * Get a distance metric function for two points based on the 65440 * axis mode setting 65441 * @param {string} axis - the axis mode. x|y|xy 65442 */ 65443function getDistanceMetricForAxis(axis) { 65444 var useX = axis.indexOf('x') !== -1; 65445 var useY = axis.indexOf('y') !== -1; 65446 65447 return function(pt1, pt2) { 65448 var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; 65449 var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; 65450 return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); 65451 }; 65452} 65453 65454function indexMode(chart, e, options) { 65455 var position = getRelativePosition(e, chart); 65456 // Default axis for index mode is 'x' to match old behaviour 65457 options.axis = options.axis || 'x'; 65458 var distanceMetric = getDistanceMetricForAxis(options.axis); 65459 var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); 65460 var elements = []; 65461 65462 if (!items.length) { 65463 return []; 65464 } 65465 65466 chart.data.datasets.forEach(function(dataset, datasetIndex) { 65467 if (chart.isDatasetVisible(datasetIndex)) { 65468 var meta = chart.getDatasetMeta(datasetIndex); 65469 var element = meta.data[items[0]._index]; 65470 65471 // don't count items that are skipped (null data) 65472 if (element && !element._view.skip) { 65473 elements.push(element); 65474 } 65475 } 65476 }); 65477 65478 return elements; 65479} 65480 65481/** 65482 * @interface IInteractionOptions 65483 */ 65484/** 65485 * If true, only consider items that intersect the point 65486 * @name IInterfaceOptions#boolean 65487 * @type Boolean 65488 */ 65489 65490/** 65491 * Contains interaction related functions 65492 * @namespace Chart.Interaction 65493 */ 65494var core_interaction = { 65495 // Helper function for different modes 65496 modes: { 65497 single: function(chart, e) { 65498 var position = getRelativePosition(e, chart); 65499 var elements = []; 65500 65501 parseVisibleItems(chart, function(element) { 65502 if (element.inRange(position.x, position.y)) { 65503 elements.push(element); 65504 return elements; 65505 } 65506 }); 65507 65508 return elements.slice(0, 1); 65509 }, 65510 65511 /** 65512 * @function Chart.Interaction.modes.label 65513 * @deprecated since version 2.4.0 65514 * @todo remove at version 3 65515 * @private 65516 */ 65517 label: indexMode, 65518 65519 /** 65520 * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something 65521 * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item 65522 * @function Chart.Interaction.modes.index 65523 * @since v2.4.0 65524 * @param {Chart} chart - the chart we are returning items from 65525 * @param {Event} e - the event we are find things at 65526 * @param {IInteractionOptions} options - options to use during interaction 65527 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65528 */ 65529 index: indexMode, 65530 65531 /** 65532 * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something 65533 * If the options.intersect is false, we find the nearest item and return the items in that dataset 65534 * @function Chart.Interaction.modes.dataset 65535 * @param {Chart} chart - the chart we are returning items from 65536 * @param {Event} e - the event we are find things at 65537 * @param {IInteractionOptions} options - options to use during interaction 65538 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65539 */ 65540 dataset: function(chart, e, options) { 65541 var position = getRelativePosition(e, chart); 65542 options.axis = options.axis || 'xy'; 65543 var distanceMetric = getDistanceMetricForAxis(options.axis); 65544 var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); 65545 65546 if (items.length > 0) { 65547 items = chart.getDatasetMeta(items[0]._datasetIndex).data; 65548 } 65549 65550 return items; 65551 }, 65552 65553 /** 65554 * @function Chart.Interaction.modes.x-axis 65555 * @deprecated since version 2.4.0. Use index mode and intersect == true 65556 * @todo remove at version 3 65557 * @private 65558 */ 65559 'x-axis': function(chart, e) { 65560 return indexMode(chart, e, {intersect: false}); 65561 }, 65562 65563 /** 65564 * Point mode returns all elements that hit test based on the event position 65565 * of the event 65566 * @function Chart.Interaction.modes.intersect 65567 * @param {Chart} chart - the chart we are returning items from 65568 * @param {Event} e - the event we are find things at 65569 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65570 */ 65571 point: function(chart, e) { 65572 var position = getRelativePosition(e, chart); 65573 return getIntersectItems(chart, position); 65574 }, 65575 65576 /** 65577 * nearest mode returns the element closest to the point 65578 * @function Chart.Interaction.modes.intersect 65579 * @param {Chart} chart - the chart we are returning items from 65580 * @param {Event} e - the event we are find things at 65581 * @param {IInteractionOptions} options - options to use 65582 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65583 */ 65584 nearest: function(chart, e, options) { 65585 var position = getRelativePosition(e, chart); 65586 options.axis = options.axis || 'xy'; 65587 var distanceMetric = getDistanceMetricForAxis(options.axis); 65588 return getNearestItems(chart, position, options.intersect, distanceMetric); 65589 }, 65590 65591 /** 65592 * x mode returns the elements that hit-test at the current x coordinate 65593 * @function Chart.Interaction.modes.x 65594 * @param {Chart} chart - the chart we are returning items from 65595 * @param {Event} e - the event we are find things at 65596 * @param {IInteractionOptions} options - options to use 65597 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65598 */
65599 x: function(chart, e, options) { 65600 var position = getRelativePosition(e, chart); 65601 var items = []; 65602 var intersectsItem = false; 65603 65604 parseVisibleItems(chart, function(element) { 65605 if (element.inXRange(position.x)) { 65606 items.push(element); 65607 } 65608 65609 if (element.inRange(position.x, position.y)) { 65610 intersectsItem = true; 65611 } 65612 }); 65613 65614 // If we want to trigger on an intersect and we don't have any items 65615 // that intersect the position, return nothing 65616 if (options.intersect && !intersectsItem) { 65617 items = []; 65618 } 65619 return items; 65620 }, 65621 65622 /** 65623 * y mode returns the elements that hit-test at the current y coordinate 65624 * @function Chart.Interaction.modes.y 65625 * @param {Chart} chart - the chart we are returning items from 65626 * @param {Event} e - the event we are find things at 65627 * @param {IInteractionOptions} options - options to use 65628 * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned 65629 */ 65630 y: function(chart, e, options) { 65631 var position = getRelativePosition(e, chart); 65632 var items = []; 65633 var intersectsItem = false; 65634 65635 parseVisibleItems(chart, function(element) { 65636 if (element.inYRange(position.y)) { 65637 items.push(element); 65638 } 65639 65640 if (element.inRange(position.x, position.y)) { 65641 intersectsItem = true; 65642 } 65643 }); 65644 65645 // If we want to trigger on an intersect and we don't have any items 65646 // that intersect the position, return nothing 65647 if (options.intersect && !intersectsItem) { 65648 items = []; 65649 } 65650 return items; 65651 } 65652 } 65653}; 65654 65655function filterByPosition(array, position) { 65656 return helpers$1.where(array, function(v) { 65657 return v.position === position; 65658 }); 65659} 65660 65661function sortByWeight(array, reverse) { 65662 array.forEach(function(v, i) { 65663 v._tmpIndex_ = i; 65664 return v; 65665 }); 65666 array.sort(function(a, b) { 65667 var v0 = reverse ? b : a; 65668 var v1 = reverse ? a : b; 65669 return v0.weight === v1.weight ? 65670 v0._tmpIndex_ - v1._tmpIndex_ : 65671 v0.weight - v1.weight; 65672 }); 65673 array.forEach(function(v) { 65674 delete v._tmpIndex_; 65675 }); 65676} 65677 65678function findMaxPadding(boxes) { 65679 var top = 0; 65680 var left = 0; 65681 var bottom = 0; 65682 var right = 0; 65683 helpers$1.each(boxes, function(box) { 65684 if (box.getPadding) { 65685 var boxPadding = box.getPadding(); 65686 top = Math.max(top, boxPadding.top); 65687 left = Math.max(left, boxPadding.left); 65688 bottom = Math.max(bottom, boxPadding.bottom); 65689 right = Math.max(right, boxPadding.right); 65690 } 65691 }); 65692 return { 65693 top: top, 65694 left: left, 65695 bottom: bottom, 65696 right: right 65697 }; 65698} 65699 65700function addSizeByPosition(boxes, size) { 65701 helpers$1.each(boxes, function(box) { 65702 size[box.position] += box.isHorizontal() ? box.height : box.width; 65703 }); 65704} 65705 65706core_defaults._set('global', { 65707 layout: { 65708 padding: { 65709 top: 0, 65710 right: 0, 65711 bottom: 0, 65712 left: 0 65713 } 65714 } 65715}); 65716 65717/** 65718 * @interface ILayoutItem 65719 * @prop {string} position - The position of the item in the chart layout. Possible values are 65720 * 'left', 'top', 'right', 'bottom', and 'chartArea' 65721 * @prop {number} weight - The weight used to sort the item. Higher weights are further away from the chart area 65722 * @prop {boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down 65723 * @prop {function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom) 65724 * @prop {function} update - Takes two parameters: width and height. Returns size of item 65725 * @prop {function} getPadding - Returns an object with padding on the edges 65726 * @prop {number} width - Width of item. Must be valid after update() 65727 * @prop {number} height - Height of item. Must be valid after update() 65728 * @prop {number} left - Left edge of the item. Set by layout system and cannot be used in update 65729 * @prop {number} top - Top edge of the item. Set by layout system and cannot be used in update 65730 * @prop {number} right - Right edge of the item. Set by layout system and cannot be used in update 65731 * @prop {number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update 65732 */ 65733 65734// The layout service is very self explanatory. It's responsible for the layout within a chart. 65735// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need 65736// It is this service's responsibility of carrying out that layout. 65737var core_layouts = { 65738 defaults: {}, 65739 65740 /** 65741 * Register a box to a chart. 65742 * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. 65743 * @param {Chart} chart - the chart to use 65744 * @param {ILayoutItem} item - the item to add to be layed out 65745 */
vendor: 4,697 bytes, lines 65746-65864
65746 addBox: function(chart, item) { 65747 if (!chart.boxes) { 65748 chart.boxes = []; 65749 } 65750 65751 // initialize item with default values 65752 item.fullWidth = item.fullWidth || false; 65753 item.position = item.position || 'top'; 65754 item.weight = item.weight || 0; 65755 65756 chart.boxes.push(item); 65757 }, 65758 65759 /** 65760 * Remove a layoutItem from a chart 65761 * @param {Chart} chart - the chart to remove the box from 65762 * @param {ILayoutItem} layoutItem - the item to remove from the layout 65763 */ 65764 removeBox: function(chart, layoutItem) { 65765 var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; 65766 if (index !== -1) { 65767 chart.boxes.splice(index, 1); 65768 } 65769 }, 65770 65771 /** 65772 * Sets (or updates) options on the given `item`. 65773 * @param {Chart} chart - the chart in which the item lives (or will be added to) 65774 * @param {ILayoutItem} item - the item to configure with the given options 65775 * @param {object} options - the new item options. 65776 */ 65777 configure: function(chart, item, options) { 65778 var props = ['fullWidth', 'position', 'weight']; 65779 var ilen = props.length; 65780 var i = 0; 65781 var prop; 65782 65783 for (; i < ilen; ++i) { 65784 prop = props[i]; 65785 if (options.hasOwnProperty(prop)) { 65786 item[prop] = options[prop]; 65787 } 65788 } 65789 }, 65790 65791 /** 65792 * Fits boxes of the given chart into the given size by having each box measure itself 65793 * then running a fitting algorithm 65794 * @param {Chart} chart - the chart 65795 * @param {number} width - the width to fit into 65796 * @param {number} height - the height to fit into 65797 */ 65798 update: function(chart, width, height) { 65799 if (!chart) { 65800 return; 65801 } 65802 65803 var layoutOptions = chart.options.layout || {}; 65804 var padding = helpers$1.options.toPadding(layoutOptions.padding); 65805 var leftPadding = padding.left; 65806 var rightPadding = padding.right; 65807 var topPadding = padding.top; 65808 var bottomPadding = padding.bottom; 65809 65810 var leftBoxes = filterByPosition(chart.boxes, 'left'); 65811 var rightBoxes = filterByPosition(chart.boxes, 'right'); 65812 var topBoxes = filterByPosition(chart.boxes, 'top'); 65813 var bottomBoxes = filterByPosition(chart.boxes, 'bottom'); 65814 var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea'); 65815 65816 // Sort boxes by weight. A higher weight is further away from the chart area 65817 sortByWeight(leftBoxes, true); 65818 sortByWeight(rightBoxes, false); 65819 sortByWeight(topBoxes, true); 65820 sortByWeight(bottomBoxes, false); 65821 65822 var verticalBoxes = leftBoxes.concat(rightBoxes); 65823 var horizontalBoxes = topBoxes.concat(bottomBoxes); 65824 var outerBoxes = verticalBoxes.concat(horizontalBoxes); 65825 65826 // Essentially we now have any number of boxes on each of the 4 sides. 65827 // Our canvas looks like the following. 65828 // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and 65829 // B1 is the bottom axis 65830 // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays 65831 // These locations are single-box locations only, when trying to register a chartArea location that is already taken, 65832 // an error will be thrown. 65833 // 65834 // |----------------------------------------------------| 65835 // | T1 (Full Width) | 65836 // |----------------------------------------------------| 65837 // | | | T2 | | 65838 // | |----|-------------------------------------|----| 65839 // | | | C1 | | C2 | | 65840 // | | |----| |----| | 65841 // | | | | | 65842 // | L1 | L2 | ChartArea (C0) | R1 | 65843 // | | | | | 65844 // | | |----| |----| | 65845 // | | | C3 | | C4 | | 65846 // | |----|-------------------------------------|----| 65847 // | | | B1 | | 65848 // |----------------------------------------------------| 65849 // | B2 (Full Width) | 65850 // |----------------------------------------------------| 65851 // 65852 // What we do to find the best sizing, we do the following 65853 // 1. Determine the minimum size of the chart area. 65854 // 2. Split the remaining width equally between each vertical axis 65855 // 3. Split the remaining height equally between each horizontal axis 65856 // 4. Give each layout the maximum size it can be. The layout will return it's minimum size 65857 // 5. Adjust the sizes of each axis based on it's minimum reported size. 65858 // 6. Refit each axis 65859 // 7. Position each axis in the final location 65860 // 8. Tell the chart the final location of the chart area 65861 // 9. Tell any axes that overlay the chart area the positions of the chart area 65862 65863 // Step 1 65864 var chartWidth = width - leftPadding - rightPadding;
65865 var chartHeight = height - topPadding - bottomPadding; 65866 var chartAreaWidth = chartWidth / 2; // min 50% 65867 65868 // Step 2 65869 var verticalBoxWidth = (width - chartAreaWidth) / verticalBoxes.length; 65870 65871 // Step 3 65872 // TODO re-limit horizontal axis height (this limit has affected only padding calculation since PR 1837) 65873 // var horizontalBoxHeight = (height - chartAreaHeight) / horizontalBoxes.length; 65874 65875 // Step 4 65876 var maxChartAreaWidth = chartWidth; 65877 var maxChartAreaHeight = chartHeight; 65878 var outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding}; 65879 var minBoxSizes = []; 65880 var maxPadding; 65881 65882 function getMinimumBoxSize(box) { 65883 var minSize; 65884 var isHorizontal = box.isHorizontal(); 65885 65886 if (isHorizontal) { 65887 minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2); 65888 maxChartAreaHeight -= minSize.height; 65889 } else { 65890 minSize = box.update(verticalBoxWidth, maxChartAreaHeight); 65891 maxChartAreaWidth -= minSize.width; 65892 } 65893 65894 minBoxSizes.push({ 65895 horizontal: isHorizontal, 65896 width: minSize.width, 65897 box: box, 65898 }); 65899 } 65900 65901 helpers$1.each(outerBoxes, getMinimumBoxSize); 65902 65903 // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478) 65904 maxPadding = findMaxPadding(outerBoxes); 65905 65906 // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could 65907 // be if the axes are drawn at their minimum sizes. 65908 // Steps 5 & 6 65909 65910 // Function to fit a box 65911 function fitBox(box) { 65912 var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minBox) { 65913 return minBox.box === box; 65914 }); 65915 65916 if (minBoxSize) { 65917 if (minBoxSize.horizontal) { 65918 var scaleMargin = { 65919 left: Math.max(outerBoxSizes.left, maxPadding.left), 65920 right: Math.max(outerBoxSizes.right, maxPadding.right), 65921 top: 0, 65922 bottom: 0 65923 }; 65924 65925 // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends 65926 // on the margin. Sometimes they need to increase in size slightly 65927 box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin); 65928 } else { 65929 box.update(minBoxSize.width, maxChartAreaHeight); 65930 } 65931 } 65932 } 65933 65934 // Update, and calculate the left and right margins for the horizontal boxes 65935 helpers$1.each(verticalBoxes, fitBox); 65936 addSizeByPosition(verticalBoxes, outerBoxSizes); 65937 65938 // Set the Left and Right margins for the horizontal boxes 65939 helpers$1.each(horizontalBoxes, fitBox); 65940 addSizeByPosition(horizontalBoxes, outerBoxSizes); 65941 65942 function finalFitVerticalBox(box) { 65943 var minBoxSize = helpers$1.findNextWhere(minBoxSizes, function(minSize) { 65944 return minSize.box === box; 65945 }); 65946 65947 var scaleMargin = { 65948 left: 0, 65949 right: 0, 65950 top: outerBoxSizes.top, 65951 bottom: outerBoxSizes.bottom 65952 }; 65953 65954 if (minBoxSize) { 65955 box.update(minBoxSize.width, maxChartAreaHeight, scaleMargin); 65956 } 65957 } 65958 65959 // Let the left layout know the final margin 65960 helpers$1.each(verticalBoxes, finalFitVerticalBox); 65961 65962 // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance) 65963 outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding}; 65964 addSizeByPosition(outerBoxes, outerBoxSizes); 65965 65966 // We may be adding some padding to account for rotated x axis labels 65967 var leftPaddingAddition = Math.max(maxPadding.left - outerBoxSizes.left, 0); 65968 outerBoxSizes.left += leftPaddingAddition; 65969 outerBoxSizes.right += Math.max(maxPadding.right - outerBoxSizes.right, 0); 65970 65971 var topPaddingAddition = Math.max(maxPadding.top - outerBoxSizes.top, 0); 65972 outerBoxSizes.top += topPaddingAddition; 65973 outerBoxSizes.bottom += Math.max(maxPadding.bottom - outerBoxSizes.bottom, 0); 65974 65975 // Figure out if our chart area changed. This would occur if the dataset layout label rotation 65976 // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do 65977 // without calling `fit` again 65978 var newMaxChartAreaHeight = height - outerBoxSizes.top - outerBoxSizes.bottom; 65979 var newMaxChartAreaWidth = width - outerBoxSizes.left - outerBoxSizes.right; 65980 65981 if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) { 65982 helpers$1.each(verticalBoxes, function(box) { 65983 box.height = newMaxChartAreaHeight; 65984 }); 65985 65986 helpers$1.each(horizontalBoxes, function(box) { 65987 if (!box.fullWidth) { 65988 box.width = newMaxChartAreaWidth; 65989 } 65990 }); 65991 65992 maxChartAreaHeight = newMaxChartAreaHeight; 65993 maxChartAreaWidth = newMaxChartAreaWidth; 65994 } 65995 65996 // Step 7 - Position the boxes 65997 var left = leftPadding + leftPaddingAddition; 65998 var top = topPadding + topPaddingAddition; 65999 66000 function placeBox(box) { 66001 if (box.isHorizontal()) { 66002 box.left = box.fullWidth ? leftPadding : outerBoxSizes.left; 66003 box.right = box.fullWidth ? width - rightPadding : outerBoxSizes.left + maxChartAreaWidth; 66004 box.top = top; 66005 box.bottom = top + box.height; 66006 66007 // Move to next point 66008 top = box.bottom; 66009 66010 } else { 66011 66012 box.left = left; 66013 box.right = left + box.width; 66014 box.top = outerBoxSizes.top; 66015 box.bottom = outerBoxSizes.top + maxChartAreaHeight; 66016 66017 // Move to next point 66018 left = box.right; 66019 } 66020 } 66021 66022 helpers$1.each(leftBoxes.concat(topBoxes), placeBox); 66023 66024 // Account for chart width and height 66025 left += maxChartAreaWidth; 66026 top += maxChartAreaHeight; 66027 66028 helpers$1.each(rightBoxes, placeBox); 66029 helpers$1.each(bottomBoxes, placeBox); 66030 66031 // Step 8 66032 chart.chartArea = { 66033 left: outerBoxSizes.left, 66034 top: outerBoxSizes.top, 66035 right: outerBoxSizes.left + maxChartAreaWidth, 66036 bottom: outerBoxSizes.top + maxChartAreaHeight 66037 }; 66038 66039 // Step 9 66040 helpers$1.each(chartAreaBoxes, function(box) { 66041 box.left = chart.chartArea.left; 66042 box.top = chart.chartArea.top; 66043 box.right = chart.chartArea.right; 66044 box.bottom = chart.chartArea.bottom; 66045 66046 box.update(maxChartAreaWidth, maxChartAreaHeight); 66047 }); 66048 } 66049}; 66050 66051/** 66052 * Platform fallback implementation (minimal). 66053 * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939 66054 */ 66055 66056var platform_basic = { 66057 acquireContext: function(item) { 66058 if (item && item.canvas) {
66059 // Support for any object associated to a canvas (including a context2d) 66060 item = item.canvas; 66061 } 66062 66063 return item && item.getContext('2d') || null; 66064 } 66065}; 66066 66067var platform_dom = "/*\n * DOM element rendering detection\n * https://davidwalsh.name/detect-node-insertion\n */\n@keyframes chartjs-render-animation {\n\tfrom { opacity: 0.99; }\n\tto { opacity: 1; }\n}\n\n.chartjs-render-monitor {\n\tanimation: chartjs-render-animation 0.001s;\n}\n\n/*\n * DOM element resizing detection\n * https://github.com/marcj/css-element-queries\n */\n.chartjs-size-monitor,\n.chartjs-size-monitor-expand,\n.chartjs-size-monitor-shrink {\n\tposition: absolute;\n\tdirection: ltr;\n\tleft: 0;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\tvisibility: hidden;\n\tz-index: -1;\n}\n\n.chartjs-size-monitor-expand > div {\n\tposition: absolute;\n\twidth: 1000000px;\n\theight: 1000000px;\n\tleft: 0;\n\ttop: 0;\n}\n\n.chartjs-size-monitor-shrink > div {\n\tposition: absolute;\n\twidth: 200%;\n\theight: 200%;\n\tleft: 0;\n\ttop: 0;\n}\n"; 66068 66069var platform_dom$1 = /*#__PURE__*/Object.freeze({ 66070default: platform_dom 66071}); 66072 66073var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 66074 66075function commonjsRequire () { 66076 throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); 66077} 66078 66079function createCommonjsModule(fn, module) { 66080 return module = { exports: {} }, fn(module, module.exports), module.exports; 66081} 66082 66083function getCjsExportFromNamespace (n) { 66084 return n && n.default || n; 66085} 66086 66087var stylesheet = getCjsExportFromNamespace(platform_dom$1); 66088 66089var EXPANDO_KEY = '$chartjs'; 66090var CSS_PREFIX = 'chartjs-'; 66091var CSS_SIZE_MONITOR = CSS_PREFIX + 'size-monitor'; 66092var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor'; 66093var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation'; 66094var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart']; 66095 66096/** 66097 * DOM event types -> Chart.js event types. 66098 * Note: only events with different types are mapped. 66099 * @see https://developer.mozilla.org/en-US/docs/Web/Events 66100 */ 66101var EVENT_TYPES = { 66102 touchstart: 'mousedown', 66103 touchmove: 'mousemove', 66104 touchend: 'mouseup', 66105 pointerenter: 'mouseenter', 66106 pointerdown: 'mousedown', 66107 pointermove: 'mousemove', 66108 pointerup: 'mouseup', 66109 pointerleave: 'mouseout', 66110 pointerout: 'mouseout' 66111}; 66112 66113/** 66114 * The "used" size is the final value of a dimension property after all calculations have 66115 * been performed. This method uses the computed style of `element` but returns undefined 66116 * if the computed style is not expressed in pixels. That can happen in some cases where 66117 * `element` has a size relative to its parent and this last one is not yet displayed, 66118 * for example because of `display: none` on a parent node. 66119 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value 66120 * @returns {number} Size in pixels or undefined if unknown. 66121 */ 66122function readUsedSize(element, property) { 66123 var value = helpers$1.getStyle(element, property); 66124 var matches = value && value.match(/^(\d+)(\.\d+)?px$/); 66125 return matches ? Number(matches[1]) : undefined; 66126} 66127 66128/** 66129 * Initializes the canvas style and render size without modifying the canvas display size, 66130 * since responsiveness is handled by the controller.resize() method. The config is used 66131 * to determine the aspect ratio to apply in case no explicit height has been specified. 66132 */ 66133function initCanvas(canvas, config) { 66134 var style = canvas.style; 66135 66136 // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it 66137 // returns null or '' if no explicit value has been set to the canvas attribute. 66138 var renderHeight = canvas.getAttribute('height'); 66139 var renderWidth = canvas.getAttribute('width'); 66140 66141 // Chart.js modifies some canvas values that we want to restore on de
vendor: 99,514 bytes, lines 66141-69677
66141stroy 66142 canvas[EXPANDO_KEY] = { 66143 initial: { 66144 height: renderHeight, 66145 width: renderWidth, 66146 style: { 66147 display: style.display, 66148 height: style.height, 66149 width: style.width 66150 } 66151 } 66152 }; 66153 66154 // Force canvas to display as block to avoid extra space caused by inline 66155 // elements, which would interfere with the responsive resize process. 66156 // https://github.com/chartjs/Chart.js/issues/2538 66157 style.display = style.display || 'block'; 66158 66159 if (renderWidth === null || renderWidth === '') { 66160 var displayWidth = readUsedSize(canvas, 'width'); 66161 if (displayWidth !== undefined) { 66162 canvas.width = displayWidth; 66163 } 66164 } 66165 66166 if (renderHeight === null || renderHeight === '') { 66167 if (canvas.style.height === '') { 66168 // If no explicit render height and style height, let's apply the aspect ratio, 66169 // which one can be specified by the user but also by charts as default option 66170 // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. 66171 canvas.height = canvas.width / (config.options.aspectRatio || 2); 66172 } else { 66173 var displayHeight = readUsedSize(canvas, 'height'); 66174 if (displayWidth !== undefined) { 66175 canvas.height = displayHeight; 66176 } 66177 } 66178 } 66179 66180 return canvas; 66181} 66182 66183/** 66184 * Detects support for options object argument in addEventListener. 66185 * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support 66186 * @private 66187 */ 66188var supportsEventListenerOptions = (function() { 66189 var supports = false; 66190 try { 66191 var options = Object.defineProperty({}, 'passive', { 66192 // eslint-disable-next-line getter-return 66193 get: function() { 66194 supports = true; 66195 } 66196 }); 66197 window.addEventListener('e', null, options); 66198 } catch (e) { 66199 // continue regardless of error 66200 } 66201 return supports; 66202}()); 66203 66204// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events. 66205// https://github.com/chartjs/Chart.js/issues/4287 66206var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false; 66207 66208function addListener(node, type, listener) { 66209 node.addEventListener(type, listener, eventListenerOptions); 66210} 66211 66212function removeListener(node, type, listener) { 66213 node.removeEventListener(type, listener, eventListenerOptions); 66214} 66215 66216function createEvent(type, chart, x, y, nativeEvent) { 66217 return { 66218 type: type, 66219 chart: chart, 66220 native: nativeEvent || null, 66221 x: x !== undefined ? x : null, 66222 y: y !== undefined ? y : null, 66223 }; 66224} 66225 66226function fromNativeEvent(event, chart) { 66227 var type = EVENT_TYPES[event.type] || event.type; 66228 var pos = helpers$1.getRelativePosition(event, chart); 66229 return createEvent(type, chart, pos.x, pos.y, event); 66230} 66231 66232function throttled(fn, thisArg) { 66233 var ticking = false; 66234 var args = []; 66235 66236 return function() { 66237 args = Array.prototype.slice.call(arguments); 66238 thisArg = thisArg || this; 66239 66240 if (!ticking) { 66241 ticking = true; 66242 helpers$1.requestAnimFrame.call(window, function() { 66243 ticking = false; 66244 fn.apply(thisArg, args); 66245 }); 66246 } 66247 }; 66248} 66249 66250function createDiv(cls) { 66251 var el = document.createElement('div'); 66252 el.className = cls || ''; 66253 return el; 66254} 66255 66256// Implementation based on https://github.com/marcj/css-element-queries 66257function createResizer(handler) { 66258 var maxSize = 1000000; 66259 66260 // NOTE(SB) Don't use innerHTML because it could be considered unsafe. 66261 // https://github.com/chartjs/Chart.js/issues/5902 66262 var resizer = createDiv(CSS_SIZE_MONITOR); 66263 var expand = createDiv(CSS_SIZE_MONITOR + '-expand'); 66264 var shrink = createDiv(CSS_SIZE_MONITOR + '-shrink'); 66265 66266 expand.appendChild(createDiv()); 66267 shrink.appendChild(createDiv()); 66268 66269 resizer.appendChild(expand); 66270 resizer.appendChild(shrink); 66271 resizer._reset = function() { 66272 expand.scrollLeft = maxSize; 66273 expand.scrollTop = maxSize; 66274 shrink.scrollLeft = maxSize; 66275 shrink.scrollTop = maxSize; 66276 }; 66277 66278 var onScroll = function() { 66279 resizer._reset(); 66280 handler(); 66281 }; 66282 66283 addListener(expand, 'scroll', onScroll.bind(expand, 'expand')); 66284 addListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink')); 66285 66286 return resizer; 66287} 66288 66289// https://davidwalsh.name/detect-node-insertion 66290function watchForRender(node, handler) { 66291 var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); 66292 var proxy = expando.renderProxy = function(e) { 66293 if (e.animationName === CSS_RENDER_ANIMATION) { 66294 handler(); 66295 } 66296 }; 66297 66298 helpers$1.each(ANIMATION_START_EVENTS, function(type) { 66299 addListener(node, type, proxy); 66300 }); 66301 66302 // #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class 66303 // is removed then added back immediately (same animation frame?). Accessing the 66304 // `offsetParent` property will force a reflow and re-evaluate the CSS animation. 66305 // https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics 66306 // https://github.com/chartjs/Chart.js/issues/4737 66307 expando.reflow = !!node.offsetParent; 66308 66309 node.classList.add(CSS_RENDER_MONITOR); 66310} 66311 66312function unwatchForRender(node) { 66313 var expando = node[EXPANDO_KEY] || {}; 66314 var proxy = expando.renderProxy; 66315 66316 if (proxy) { 66317 helpers$1.each(ANIMATION_START_EVENTS, function(type) { 66318 removeListener(node, type, proxy); 66319 }); 66320 66321 delete expando.renderProxy; 66322 } 66323 66324 node.classList.remove(CSS_RENDER_MONITOR); 66325} 66326 66327function addResizeListener(node, listener, chart) { 66328 var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); 66329 66330 // Let's keep track of this added resizer and thus avoid DOM query when removing it. 66331 var resizer = expando.resizer = createResizer(throttled(function() { 66332 if (expando.resizer) { 66333 var container = chart.options.maintainAspectRatio && node.parentNode; 66334 var w = container ? container.clientWidth : 0; 66335 listener(createEvent('resize', chart)); 66336 if (container && container.clientWidth < w && chart.canvas) { 66337 // If the container size shrank during chart resize, let's assume 66338 // scrollbar appeared. So we resize again with the scrollbar visible - 66339 // effectively making chart smaller and the scrollbar hidden again. 66340 // Because we are inside `throttled`, and currently `ticking`, scroll 66341 // events are ignored during this whole 2 resize process. 66342 // If we assumed wrong and something else happened, we are resizing 66343 // twice in a frame (potential performance issue) 66344 listener(createEvent('resize', chart)); 66345 } 66346 } 66347 })); 66348 66349 // The resizer needs to be attached to the node parent, so we first need to be 66350 // sure that `node` is attached to the DOM before injecting the resizer element. 66351 watchForRender(node, function() { 66352 if (expando.resizer) { 66353 var container = node.parentNode; 66354 if (container && container !== resizer.parentNode) { 66355 container.insertBefore(resizer, container.firstChild); 66356 } 66357 66358 // The container size might have changed, let's reset the resizer state. 66359 resizer._reset(); 66360 } 66361 }); 66362} 66363 66364function removeResizeListener(node) { 66365 var expando = node[EXPANDO_KEY] || {}; 66366 var resizer = expando.resizer; 66367 66368 delete expando.resizer; 66369 unwatchForRender(node); 66370 66371 if (resizer && resizer.parentNode) { 66372 resizer.parentNode.removeChild(resizer); 66373 } 66374} 66375 66376function injectCSS(platform, css) { 66377 // https://stackoverflow.com/q/3922139 66378 var style = platform._style || document.createElement('style'); 66379 if (!platform._style) { 66380 platform._style = style; 66381 css = '/* Chart.js */\n' + css; 66382 style.setAttribute('type', 'text/css'); 66383 document.getElementsByTagName('head')[0].appendChild(style); 66384 } 66385 66386 style.appendChild(document.createTextNode(css)); 66387} 66388 66389var platform_dom$2 = { 66390 /** 66391 * When `true`, prevents the automatic injection of the stylesheet required to 66392 * correctly detect when the chart is added to the DOM and then resized. This 66393 * switch has been added to allow external stylesheet (`dist/Chart(.min)?.js`) 66394 * to be manually imported to make this library compatible with any CSP. 66395 * See https://github.com/chartjs/Chart.js/issues/5208 66396 */ 66397 disableCSSInjection: false, 66398 66399 /** 66400 * This property holds whether this platform is enabled for the current environment. 66401 * Currently used by platform.js to select the proper implementation. 66402 * @private 66403 */ 66404 _enabled: typeof window !== 'undefined' && typeof document !== 'undefined', 66405 66406 /** 66407 * @private 66408 */ 66409 _ensureLoaded: function() { 66410 if (this._loaded) { 66411 return; 66412 } 66413 66414 this._loaded = true; 66415 66416 // https://github.com/chartjs/Chart.js/issues/5208 66417 if (!this.disableCSSInjection) { 66418 injectCSS(this, stylesheet); 66419 } 66420 }, 66421 66422 acquireContext: function(item, config) { 66423 if (typeof item === 'string') { 66424 item = document.getElementById(item); 66425 } else if (item.length) { 66426 // Support for array based queries (such as jQuery) 66427 item = item[0]; 66428 } 66429 66430 if (item && item.canvas) { 66431 // Support for any object associated to a canvas (including a context2d) 66432 item = item.canvas; 66433 } 66434 66435 // To prevent canvas fingerprinting, some add-ons undefine the getContext 66436 // method, for example: https://github.com/kkapsner/CanvasBlocker 66437 // https://github.com/chartjs/Chart.js/issues/2807 66438 var context = item && item.getContext && item.getContext('2d'); 66439 66440 // Load platform resources on first chart creation, to make possible to change 66441 // platform options after importing the library (e.g. `disableCSSInjection`). 66442 this._ensureLoaded(); 66443 66444 // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is 66445 // inside an iframe or when running in a protected environment. We could guess the 66446 // types from their toString() value but let's keep things flexible and assume it's 66447 // a sufficient condition if the item has a context2D which has item as `canvas`. 66448 // https://github.com/chartjs/Chart.js/issues/3887 66449 // https://github.com/chartjs/Chart.js/issues/4102 66450 // https://github.com/chartjs/Chart.js/issues/4152 66451 if (context && context.canvas === item) { 66452 initCanvas(item, config); 66453 return context; 66454 } 66455 66456 return null; 66457 }, 66458 66459 releaseContext: function(context) { 66460 var canvas = context.canvas; 66461 if (!canvas[EXPANDO_KEY]) { 66462 return; 66463 } 66464 66465 var initial = canvas[EXPANDO_KEY].initial; 66466 ['height', 'width'].forEach(function(prop) { 66467 var value = initial[prop]; 66468 if (helpers$1.isNullOrUndef(value)) { 66469 canvas.removeAttribute(prop); 66470 } else { 66471 canvas.setAttribute(prop, value); 66472 } 66473 }); 66474 66475 helpers$1.each(initial.style || {}, function(value, key) { 66476 canvas.style[key] = value; 66477 }); 66478 66479 // The canvas render size might have been changed (and thus the state stack discarded), 66480 // we can't use save() and restore() to restore the initial state. So make sure that at 66481 // least the canvas context is reset to the default state by setting the canvas width. 66482 // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html 66483 // eslint-disable-next-line no-self-assign 66484 canvas.width = canvas.width; 66485 66486 delete canvas[EXPANDO_KEY]; 66487 }, 66488 66489 addEventListener: function(chart, type, listener) { 66490 var canvas = chart.canvas; 66491 if (type === 'resize') { 66492 // Note: the resize event is not supported on all browsers. 66493 addResizeListener(canvas, listener, chart); 66494 return; 66495 } 66496 66497 var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {}); 66498 var proxies = expando.proxies || (expando.proxies = {}); 66499 var proxy = proxies[chart.id + '_' + type] = function(event) { 66500 listener(fromNativeEvent(event, chart)); 66501 }; 66502 66503 addListener(canvas, type, proxy); 66504 }, 66505 66506 removeEventListener: function(chart, type, listener) { 66507 var canvas = chart.canvas; 66508 if (type === 'resize') { 66509 // Note: the resize event is not supported on all browsers. 66510 removeResizeListener(canvas); 66511 return; 66512 } 66513 66514 var expando = listener[EXPANDO_KEY] || {}; 66515 var proxies = expando.proxies || {}; 66516 var proxy = proxies[chart.id + '_' + type]; 66517 if (!proxy) { 66518 return; 66519 } 66520 66521 removeListener(canvas, type, proxy); 66522 } 66523}; 66524 66525// DEPRECATIONS 66526 66527/** 66528 * Provided for backward compatibility, use EventTarget.addEventListener instead. 66529 * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ 66530 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener 66531 * @function Chart.helpers.addEvent 66532 * @deprecated since version 2.7.0 66533 * @todo remove at version 3 66534 * @private 66535 */ 66536helpers$1.addEvent = addListener; 66537 66538/** 66539 * Provided for backward compatibility, use EventTarget.removeEventListener instead. 66540 * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ 66541 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener 66542 * @function Chart.helpers.removeEvent 66543 * @deprecated since version 2.7.0 66544 * @todo remove at version 3 66545 * @private 66546 */ 66547helpers$1.removeEvent = removeListener; 66548 66549// @TODO Make possible to select another platform at build time. 66550var implementation = platform_dom$2._enabled ? platform_dom$2 : platform_basic; 66551 66552/** 66553 * @namespace Chart.platform 66554 * @see https://chartjs.gitbooks.io/proposals/content/Platform.html 66555 * @since 2.4.0 66556 */ 66557var platform = helpers$1.extend({ 66558 /** 66559 * @since 2.7.0 66560 */ 66561 initialize: function() {}, 66562 66563 /** 66564 * Called at chart construction time, returns a context2d instance implementing 66565 * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}. 66566 * @param {*} item - The native item from which to acquire context (platform specific) 66567 * @param {object} options - The chart options 66568 * @returns {CanvasRenderingContext2D} context2d instance 66569 */ 66570 acquireContext: function() {}, 66571 66572 /** 66573 * Called at chart destruction time, releases any resources associated to the context 66574 * previously returned by the acquireContext() method. 66575 * @param {CanvasRenderingContext2D} context - The context2d instance 66576 * @returns {boolean} true if the method succeeded, else false 66577 */ 66578 releaseContext: function() {}, 66579 66580 /** 66581 * Registers the specified listener on the given chart. 66582 * @param {Chart} chart - Chart from which to listen for event 66583 * @param {string} type - The ({@link IEvent}) type to listen for 66584 * @param {function} listener - Receives a notification (an object that implements 66585 * the {@link IEvent} interface) when an event of the specified type occurs. 66586 */ 66587 addEventListener: function() {}, 66588 66589 /** 66590 * Removes the specified listener previously registered with addEventListener. 66591 * @param {Chart} chart - Chart from which to remove the listener 66592 * @param {string} type - The ({@link IEvent}) type to remove 66593 * @param {function} listener - The listener function to remove from the event target. 66594 */ 66595 removeEventListener: function() {} 66596 66597}, implementation); 66598 66599core_defaults._set('global', { 66600 plugins: {} 66601}); 66602 66603/** 66604 * The plugin service singleton 66605 * @namespace Chart.plugins 66606 * @since 2.1.0 66607 */ 66608var core_plugins = { 66609 /** 66610 * Globally registered plugins. 66611 * @private 66612 */ 66613 _plugins: [], 66614 66615 /** 66616 * This identifier is used to invalidate the descriptors cache attached to each chart 66617 * when a global plugin is registered or unregistered. In this case, the cache ID is 66618 * incremented and descriptors are regenerated during following API calls. 66619 * @private 66620 */ 66621 _cacheId: 0, 66622 66623 /** 66624 * Registers the given plugin(s) if not already registered. 66625 * @param {IPlugin[]|IPlugin} plugins plugin instance(s). 66626 */ 66627 register: function(plugins) { 66628 var p = this._plugins; 66629 ([]).concat(plugins).forEach(function(plugin) { 66630 if (p.indexOf(plugin) === -1) { 66631 p.push(plugin); 66632 } 66633 }); 66634 66635 this._cacheId++; 66636 }, 66637 66638 /** 66639 * Unregisters the given plugin(s) only if registered. 66640 * @param {IPlugin[]|IPlugin} plugins plugin instance(s). 66641 */ 66642 unregister: function(plugins) { 66643 var p = this._plugins; 66644 ([]).concat(plugins).forEach(function(plugin) { 66645 var idx = p.indexOf(plugin); 66646 if (idx !== -1) { 66647 p.splice(idx, 1); 66648 } 66649 }); 66650 66651 this._cacheId++; 66652 }, 66653 66654 /** 66655 * Remove all registered plugins. 66656 * @since 2.1.5 66657 */ 66658 clear: function() { 66659 this._plugins = []; 66660 this._cacheId++; 66661 }, 66662 66663 /** 66664 * Returns the number of registered plugins? 66665 * @returns {number} 66666 * @since 2.1.5 66667 */ 66668 count: function() { 66669 return this._plugins.length; 66670 }, 66671 66672 /** 66673 * Returns all registered plugin instances. 66674 * @returns {IPlugin[]} array of plugin objects. 66675 * @since 2.1.5 66676 */ 66677 getAll: function() { 66678 return this._plugins; 66679 }, 66680 66681 /** 66682 * Calls enabled plugins for `chart` on the specified hook and with the given args. 66683 * This method immediately returns as soon as a plugin explicitly returns false. The 66684 * returned value can be used, for instance, to interrupt the current action. 66685 * @param {Chart} chart - The chart instance for which plugins should be called. 66686 * @param {string} hook - The name of the plugin method to call (e.g. 'beforeUpdate'). 66687 * @param {Array} [args] - Extra arguments to apply to the hook call. 66688 * @returns {boolean} false if any of the plugins return false, else returns true. 66689 */ 66690 notify: function(chart, hook, args) { 66691 var descriptors = this.descriptors(chart); 66692 var ilen = descriptors.length; 66693 var i, descriptor, plugin, params, method; 66694 66695 for (i = 0; i < ilen; ++i) { 66696 descriptor = descriptors[i]; 66697 plugin = descriptor.plugin; 66698 method = plugin[hook]; 66699 if (typeof method === 'function') { 66700 params = [chart].concat(args || []); 66701 params.push(descriptor.options); 66702 if (method.apply(plugin, params) === false) { 66703 return false; 66704 } 66705 } 66706 } 66707 66708 return true; 66709 }, 66710 66711 /** 66712 * Returns descriptors of enabled plugins for the given chart. 66713 * @returns {object[]} [{ plugin, options }] 66714 * @private 66715 */ 66716 descriptors: function(chart) { 66717 var cache = chart.$plugins || (chart.$plugins = {}); 66718 if (cache.id === this._cacheId) { 66719 return cache.descriptors; 66720 } 66721 66722 var plugins = []; 66723 var descriptors = []; 66724 var config = (chart && chart.config) || {}; 66725 var options = (config.options && config.options.plugins) || {}; 66726 66727 this._plugins.concat(config.plugins || []).forEach(function(plugin) { 66728 var idx = plugins.indexOf(plugin); 66729 if (idx !== -1) { 66730 return; 66731 } 66732 66733 var id = plugin.id; 66734 var opts = options[id]; 66735 if (opts === false) { 66736 return; 66737 } 66738 66739 if (opts === true) { 66740 opts = helpers$1.clone(core_defaults.global.plugins[id]); 66741 } 66742 66743 plugins.push(plugin); 66744 descriptors.push({ 66745 plugin: plugin, 66746 options: opts || {} 66747 }); 66748 }); 66749 66750 cache.descriptors = descriptors; 66751 cache.id = this._cacheId; 66752 return descriptors; 66753 }, 66754 66755 /** 66756 * Invalidates cache for the given chart: descriptors hold a reference on plugin option, 66757 * but in some cases, this reference can be changed by the user when updating options. 66758 * https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167 66759 * @private 66760 */ 66761 _invalidate: function(chart) { 66762 delete chart.$plugins; 66763 } 66764}; 66765 66766var core_scaleService = { 66767 // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then 66768 // use the new chart options to grab the correct scale 66769 constructors: {}, 66770 // Use a registration function so that we can move to an ES6 map when we no longer need to support 66771 // old browsers 66772 66773 // Scale config defaults 66774 defaults: {}, 66775 registerScaleType: function(type, scaleConstructor, scaleDefaults) { 66776 this.constructors[type] = scaleConstructor; 66777 this.defaults[type] = helpers$1.clone(scaleDefaults); 66778 }, 66779 getScaleConstructor: function(type) { 66780 return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined; 66781 }, 66782 getScaleDefaults: function(type) { 66783 // Return the scale defaults merged with the global settings so that we always use the latest ones 66784 return this.defaults.hasOwnProperty(type) ? helpers$1.merge({}, [core_defaults.scale, this.defaults[type]]) : {}; 66785 }, 66786 updateScaleDefaults: function(type, additions) { 66787 var me = this; 66788 if (me.defaults.hasOwnProperty(type)) { 66789 me.defaults[type] = helpers$1.extend(me.defaults[type], additions); 66790 } 66791 }, 66792 addScalesToLayout: function(chart) { 66793 // Adds each scale to the chart.boxes array to be sized accordingly 66794 helpers$1.each(chart.scales, function(scale) { 66795 // Set ILayoutItem parameters for backwards compatibility 66796 scale.fullWidth = scale.options.fullWidth; 66797 scale.position = scale.options.position; 66798 scale.weight = scale.options.weight; 66799 core_layouts.addBox(chart, scale); 66800 }); 66801 } 66802}; 66803 66804var valueOrDefault$7 = helpers$1.valueOrDefault; 66805 66806core_defaults._set('global', { 66807 tooltips: { 66808 enabled: true, 66809 custom: null, 66810 mode: 'nearest', 66811 position: 'average', 66812 intersect: true, 66813 backgroundColor: 'rgba(0,0,0,0.8)', 66814 titleFontStyle: 'bold', 66815 titleSpacing: 2, 66816 titleMarginBottom: 6, 66817 titleFontColor: '#fff', 66818 titleAlign: 'left', 66819 bodySpacing: 2, 66820 bodyFontColor: '#fff', 66821 bodyAlign: 'left', 66822 footerFontStyle: 'bold', 66823 footerSpacing: 2, 66824 footerMarginTop: 6, 66825 footerFontColor: '#fff', 66826 footerAlign: 'left', 66827 yPadding: 6, 66828 xPadding: 6, 66829 caretPadding: 2, 66830 caretSize: 5, 66831 cornerRadius: 6, 66832 multiKeyBackground: '#fff', 66833 displayColors: true, 66834 borderColor: 'rgba(0,0,0,0)', 66835 borderWidth: 0, 66836 callbacks: { 66837 // Args are: (tooltipItems, data) 66838 beforeTitle: helpers$1.noop, 66839 title: function(tooltipItems, data) { 66840 var title = ''; 66841 var labels = data.labels; 66842 var labelCount = labels ? labels.length : 0; 66843 66844 if (tooltipItems.length > 0) { 66845 var item = tooltipItems[0]; 66846 if (item.label) { 66847 title = item.label; 66848 } else if (item.xLabel) { 66849 title = item.xLabel; 66850 } else if (labelCount > 0 && item.index < labelCount) { 66851 title = labels[item.index]; 66852 } 66853 } 66854 66855 return title; 66856 }, 66857 afterTitle: helpers$1.noop, 66858 66859 // Args are: (tooltipItems, data) 66860 beforeBody: helpers$1.noop, 66861 66862 // Args are: (tooltipItem, data) 66863 beforeLabel: helpers$1.noop, 66864 label: function(tooltipItem, data) { 66865 var label = data.datasets[tooltipItem.datasetIndex].label || ''; 66866 66867 if (label) { 66868 label += ': '; 66869 } 66870 if (!helpers$1.isNullOrUndef(tooltipItem.value)) { 66871 label += tooltipItem.value; 66872 } else { 66873 label += tooltipItem.yLabel; 66874 } 66875 return label; 66876 }, 66877 labelColor: function(tooltipItem, chart) { 66878 var meta = chart.getDatasetMeta(tooltipItem.datasetIndex); 66879 var activeElement = meta.data[tooltipItem.index]; 66880 var view = activeElement._view; 66881 return { 66882 borderColor: view.borderColor, 66883 backgroundColor: view.backgroundColor 66884 }; 66885 }, 66886 labelTextColor: function() { 66887 return this._options.bodyFontColor; 66888 }, 66889 afterLabel: helpers$1.noop, 66890 66891 // Args are: (tooltipItems, data) 66892 afterBody: helpers$1.noop, 66893 66894 // Args are: (tooltipItems, data) 66895 beforeFooter: helpers$1.noop, 66896 footer: helpers$1.noop, 66897 afterFooter: helpers$1.noop 66898 } 66899 } 66900}); 66901 66902var positioners = { 66903 /** 66904 * Average mode places the tooltip at the average position of the elements shown 66905 * @function Chart.Tooltip.positioners.average 66906 * @param elements {ChartElement[]} the elements being displayed in the tooltip 66907 * @returns {object} tooltip position 66908 */ 66909 average: function(elements) { 66910 if (!elements.length) { 66911 return false; 66912 } 66913 66914 var i, len; 66915 var x = 0; 66916 var y = 0; 66917 var count = 0; 66918 66919 for (i = 0, len = elements.length; i < len; ++i) { 66920 var el = elements[i]; 66921 if (el && el.hasValue()) { 66922 var pos = el.tooltipPosition(); 66923 x += pos.x; 66924 y += pos.y; 66925 ++count; 66926 } 66927 } 66928 66929 return { 66930 x: x / count, 66931 y: y / count 66932 }; 66933 }, 66934 66935 /** 66936 * Gets the tooltip position nearest of the item nearest to the event position 66937 * @function Chart.Tooltip.positioners.nearest 66938 * @param elements {Chart.Element[]} the tooltip elements 66939 * @param eventPosition {object} the position of the event in canvas coordinates 66940 * @returns {object} the tooltip position 66941 */ 66942 nearest: function(elements, eventPosition) { 66943 var x = eventPosition.x; 66944 var y = eventPosition.y; 66945 var minDistance = Number.POSITIVE_INFINITY; 66946 var i, len, nearestElement; 66947 66948 for (i = 0, len = elements.length; i < len; ++i) { 66949 var el = elements[i]; 66950 if (el && el.hasValue()) { 66951 var center = el.getCenterPoint(); 66952 var d = helpers$1.distanceBetweenPoints(eventPosition, center); 66953 66954 if (d < minDistance) { 66955 minDistance = d; 66956 nearestElement = el; 66957 } 66958 } 66959 } 66960 66961 if (nearestElement) { 66962 var tp = nearestElement.tooltipPosition(); 66963 x = tp.x; 66964 y = tp.y; 66965 } 66966 66967 return { 66968 x: x, 66969 y: y 66970 }; 66971 } 66972}; 66973 66974// Helper to push or concat based on if the 2nd parameter is an array or not 66975function pushOrConcat(base, toPush) { 66976 if (toPush) { 66977 if (helpers$1.isArray(toPush)) { 66978 // base = base.concat(toPush); 66979 Array.prototype.push.apply(base, toPush); 66980 } else { 66981 base.push(toPush); 66982 } 66983 } 66984 66985 return base; 66986} 66987 66988/** 66989 * Returns array of strings split by newline 66990 * @param {string} value - The value to split by newline. 66991 * @returns {string[]} value if newline present - Returned from String split() method 66992 * @function 66993 */ 66994function splitNewlines(str) { 66995 if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) { 66996 return str.split('\n'); 66997 } 66998 return str; 66999} 67000 67001 67002/** 67003 * Private helper to create a tooltip item model 67004 * @param element - the chart element (point, arc, bar) to create the tooltip item for 67005 * @return new tooltip item 67006 */ 67007function createTooltipItem(element) { 67008 var xScale = element._xScale; 67009 var yScale = element._yScale || element._scale; // handle radar || polarArea charts 67010 var index = element._index; 67011 var datasetIndex = element._datasetIndex; 67012 var controller = element._chart.getDatasetMeta(datasetIndex).controller; 67013 var indexScale = controller._getIndexScale(); 67014 var valueScale = controller._getValueScale(); 67015 67016 return { 67017 xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '', 67018 yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '', 67019 label: indexScale ? '' + indexScale.getLabelForIndex(index, datasetIndex) : '', 67020 value: valueScale ? '' + valueScale.getLabelForIndex(index, datasetIndex) : '', 67021 index: index, 67022 datasetIndex: datasetIndex, 67023 x: element._model.x, 67024 y: element._model.y 67025 }; 67026} 67027 67028/** 67029 * Helper to get the reset model for the tooltip 67030 * @param tooltipOpts {object} the tooltip options 67031 */ 67032function getBaseModel(tooltipOpts) { 67033 var globalDefaults = core_defaults.global; 67034 67035 return { 67036 // Positioning 67037 xPadding: tooltipOpts.xPadding, 67038 yPadding: tooltipOpts.yPadding, 67039 xAlign: tooltipOpts.xAlign, 67040 yAlign: tooltipOpts.yAlign, 67041 67042 // Body 67043 bodyFontColor: tooltipOpts.bodyFontColor, 67044 _bodyFontFamily: valueOrDefault$7(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily), 67045 _bodyFontStyle: valueOrDefault$7(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle), 67046 _bodyAlign: tooltipOpts.bodyAlign, 67047 bodyFontSize: valueOrDefault$7(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize), 67048 bodySpacing: tooltipOpts.bodySpacing, 67049 67050 // Title 67051 titleFontColor: tooltipOpts.titleFontColor, 67052 _titleFontFamily: valueOrDefault$7(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily), 67053 _titleFontStyle: valueOrDefault$7(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle), 67054 titleFontSize: valueOrDefault$7(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize), 67055 _titleAlign: tooltipOpts.titleAlign, 67056 titleSpacing: tooltipOpts.titleSpacing, 67057 titleMarginBottom: tooltipOpts.titleMarginBottom, 67058 67059 // Footer 67060 footerFontColor: tooltipOpts.footerFontColor, 67061 _footerFontFamily: valueOrDefault$7(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily), 67062 _footerFontStyle: valueOrDefault$7(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle), 67063 footerFontSize: valueOrDefault$7(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize), 67064 _footerAlign: tooltipOpts.footerAlign, 67065 footerSpacing: tooltipOpts.footerSpacing, 67066 footerMarginTop: tooltipOpts.footerMarginTop, 67067 67068 // Appearance 67069 caretSize: tooltipOpts.caretSize, 67070 cornerRadius: tooltipOpts.cornerRadius, 67071 backgroundColor: tooltipOpts.backgroundColor, 67072 opacity: 0, 67073 legendColorBackground: tooltipOpts.multiKeyBackground, 67074 displayColors: tooltipOpts.displayColors, 67075 borderColor: tooltipOpts.borderColor, 67076 borderWidth: tooltipOpts.borderWidth 67077 }; 67078} 67079 67080/** 67081 * Get the size of the tooltip 67082 */ 67083function getTooltipSize(tooltip, model) { 67084 var ctx = tooltip._chart.ctx; 67085 67086 var height = model.yPadding * 2; // Tooltip Padding 67087 var width = 0; 67088 67089 // Count of all lines in the body 67090 var body = model.body; 67091 var combinedBodyLength = body.reduce(function(count, bodyItem) { 67092 return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length; 67093 }, 0); 67094 combinedBodyLength += model.beforeBody.length + model.afterBody.length; 67095 67096 var titleLineCount = model.title.length; 67097 var footerLineCount = model.footer.length; 67098 var titleFontSize = model.titleFontSize; 67099 var bodyFontSize = model.bodyFontSize; 67100 var footerFontSize = model.footerFontSize; 67101 67102 height += titleLineCount * titleFontSize; // Title Lines 67103 height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing 67104 height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin 67105 height += combinedBodyLength * bodyFontSize; // Body Lines 67106 height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing 67107 height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin 67108 height += footerLineCount * (footerFontSize); // Footer Lines 67109 height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing 67110 67111 // Title width 67112 var widthPadding = 0; 67113 var maxLineWidth = function(line) { 67114 width = Math.max(width, ctx.measureText(line).width + widthPadding); 67115 }; 67116 67117 ctx.font = helpers$1.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily); 67118 helpers$1.each(model.title, maxLineWidth); 67119 67120 // Body width 67121 ctx.font = helpers$1.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily); 67122 helpers$1.each(model.beforeBody.concat(model.afterBody), maxLineWidth); 67123 67124 // Body lines may include some extra width due to the color box 67125 widthPadding = model.displayColors ? (bodyFontSize + 2) : 0; 67126 helpers$1.each(body, function(bodyItem) { 67127 helpers$1.each(bodyItem.before, maxLineWidth); 67128 helpers$1.each(bodyItem.lines, maxLineWidth); 67129 helpers$1.each(bodyItem.after, maxLineWidth); 67130 }); 67131 67132 // Reset back to 0 67133 widthPadding = 0; 67134 67135 // Footer width 67136 ctx.font = helpers$1.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily); 67137 helpers$1.each(model.footer, maxLineWidth); 67138 67139 // Add padding 67140 width += 2 * model.xPadding; 67141 67142 return { 67143 width: width, 67144 height: height 67145 }; 67146} 67147 67148/** 67149 * Helper to get the alignment of a tooltip given the size 67150 */ 67151function determineAlignment(tooltip, size) { 67152 var model = tooltip._model; 67153 var chart = tooltip._chart; 67154 var chartArea = tooltip._chart.chartArea; 67155 var xAlign = 'center'; 67156 var yAlign = 'center'; 67157 67158 if (model.y < size.height) { 67159 yAlign = 'top'; 67160 } else if (model.y > (chart.height - size.height)) { 67161 yAlign = 'bottom'; 67162 } 67163 67164 var lf, rf; // functions to determine left, right alignment 67165 var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart 67166 var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges 67167 var midX = (chartArea.left + chartArea.right) / 2; 67168 var midY = (chartArea.top + chartArea.bottom) / 2; 67169 67170 if (yAlign === 'center') { 67171 lf = function(x) { 67172 return x <= midX; 67173 }; 67174 rf = function(x) { 67175 return x > midX; 67176 }; 67177 } else { 67178 lf = function(x) { 67179 return x <= (size.width / 2); 67180 }; 67181 rf = function(x) { 67182 return x >= (chart.width - (size.width / 2)); 67183 }; 67184 } 67185 67186 olf = function(x) { 67187 return x + size.width + model.caretSize + model.caretPadding > chart.width; 67188 }; 67189 orf = function(x) { 67190 return x - size.width - model.caretSize - model.caretPadding < 0; 67191 }; 67192 yf = function(y) { 67193 return y <= midY ? 'top' : 'bottom'; 67194 }; 67195 67196 if (lf(model.x)) { 67197 xAlign = 'left'; 67198 67199 // Is tooltip too wide and goes over the right side of the chart.? 67200 if (olf(model.x)) { 67201 xAlign = 'center'; 67202 yAlign = yf(model.y); 67203 } 67204 } else if (rf(model.x)) { 67205 xAlign = 'right'; 67206 67207 // Is tooltip too wide and goes outside left edge of canvas? 67208 if (orf(model.x)) { 67209 xAlign = 'center'; 67210 yAlign = yf(model.y); 67211 } 67212 } 67213 67214 var opts = tooltip._options; 67215 return { 67216 xAlign: opts.xAlign ? opts.xAlign : xAlign, 67217 yAlign: opts.yAlign ? opts.yAlign : yAlign 67218 }; 67219} 67220 67221/** 67222 * Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment 67223 */ 67224function getBackgroundPoint(vm, size, alignment, chart) { 67225 // Background Position 67226 var x = vm.x; 67227 var y = vm.y; 67228 67229 var caretSize = vm.caretSize; 67230 var caretPadding = vm.caretPadding; 67231 var cornerRadius = vm.cornerRadius; 67232 var xAlign = alignment.xAlign; 67233 var yAlign = alignment.yAlign; 67234 var paddingAndSize = caretSize + caretPadding; 67235 var radiusAndPadding = cornerRadius + caretPadding; 67236 67237 if (xAlign === 'right') { 67238 x -= size.width; 67239 } else if (xAlign === 'center') { 67240 x -= (size.width / 2); 67241 if (x + size.width > chart.width) { 67242 x = chart.width - size.width; 67243 } 67244 if (x < 0) { 67245 x = 0; 67246 } 67247 } 67248 67249 if (yAlign === 'top') { 67250 y += paddingAndSize; 67251 } else if (yAlign === 'bottom') { 67252 y -= size.height + paddingAndSize; 67253 } else { 67254 y -= (size.height / 2); 67255 } 67256 67257 if (yAlign === 'center') { 67258 if (xAlign === 'left') { 67259 x += paddingAndSize; 67260 } else if (xAlign === 'right') { 67261 x -= paddingAndSize; 67262 } 67263 } else if (xAlign === 'left') { 67264 x -= radiusAndPadding; 67265 } else if (xAlign === 'right') { 67266 x += radiusAndPadding; 67267 } 67268 67269 return { 67270 x: x, 67271 y: y 67272 }; 67273} 67274 67275function getAlignedX(vm, align) { 67276 return align === 'center' 67277 ? vm.x + vm.width / 2 67278 : align === 'right' 67279 ? vm.x + vm.width - vm.xPadding 67280 : vm.x + vm.xPadding; 67281} 67282 67283/** 67284 * Helper to build before and after body lines 67285 */ 67286function getBeforeAfterBodyLines(callback) { 67287 return pushOrConcat([], splitNewlines(callback)); 67288} 67289 67290var exports$3 = core_element.extend({ 67291 initialize: function() { 67292 this._model = getBaseModel(this._options); 67293 this._lastActive = []; 67294 }, 67295 67296 // Get the title 67297 // Args are: (tooltipItem, data) 67298 getTitle: function() { 67299 var me = this; 67300 var opts = me._options; 67301 var callbacks = opts.callbacks; 67302 67303 var beforeTitle = callbacks.beforeTitle.apply(me, arguments); 67304 var title = callbacks.title.apply(me, arguments); 67305 var afterTitle = callbacks.afterTitle.apply(me, arguments); 67306 67307 var lines = []; 67308 lines = pushOrConcat(lines, splitNewlines(beforeTitle)); 67309 lines = pushOrConcat(lines, splitNewlines(title)); 67310 lines = pushOrConcat(lines, splitNewlines(afterTitle)); 67311 67312 return lines; 67313 }, 67314 67315 // Args are: (tooltipItem, data) 67316 getBeforeBody: function() { 67317 return getBeforeAfterBodyLines(this._options.callbacks.beforeBody.apply(this, arguments)); 67318 }, 67319 67320 // Args are: (tooltipItem, data) 67321 getBody: function(tooltipItems, data) { 67322 var me = this; 67323 var callbacks = me._options.callbacks; 67324 var bodyItems = []; 67325 67326 helpers$1.each(tooltipItems, function(tooltipItem) { 67327 var bodyItem = { 67328 before: [], 67329 lines: [], 67330 after: [] 67331 }; 67332 pushOrConcat(bodyItem.before, splitNewlines(callbacks.beforeLabel.call(me, tooltipItem, data))); 67333 pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data)); 67334 pushOrConcat(bodyItem.after, splitNewlines(callbacks.afterLabel.call(me, tooltipItem, data))); 67335 67336 bodyItems.push(bodyItem); 67337 }); 67338 67339 return bodyItems; 67340 }, 67341 67342 // Args are: (tooltipItem, data) 67343 getAfterBody: function() { 67344 return getBeforeAfterBodyLines(this._options.callbacks.afterBody.apply(this, arguments)); 67345 }, 67346 67347 // Get the footer and beforeFooter and afterFooter lines 67348 // Args are: (tooltipItem, data) 67349 getFooter: function() { 67350 var me = this; 67351 var callbacks = me._options.callbacks; 67352 67353 var beforeFooter = callbacks.beforeFooter.apply(me, arguments); 67354 var footer = callbacks.footer.apply(me, arguments); 67355 var afterFooter = callbacks.afterFooter.apply(me, arguments); 67356 67357 var lines = []; 67358 lines = pushOrConcat(lines, splitNewlines(beforeFooter)); 67359 lines = pushOrConcat(lines, splitNewlines(footer)); 67360 lines = pushOrConcat(lines, splitNewlines(afterFooter)); 67361 67362 return lines; 67363 }, 67364 67365 update: function(changed) { 67366 var me = this; 67367 var opts = me._options; 67368 67369 // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition 67370 // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time 67371 // which breaks any animations. 67372 var existingModel = me._model; 67373 var model = me._model = getBaseModel(opts); 67374 var active = me._active; 67375 67376 var data = me._data; 67377 67378 // In the case where active.length === 0 we need to keep these at existing values for good animations 67379 var alignment = { 67380 xAlign: existingModel.xAlign, 67381 yAlign: existingModel.yAlign 67382 }; 67383 var backgroundPoint = { 67384 x: existingModel.x, 67385 y: existingModel.y 67386 }; 67387 var tooltipSize = { 67388 width: existingModel.width, 67389 height: existingModel.height 67390 }; 67391 var tooltipPosition = { 67392 x: existingModel.caretX, 67393 y: existingModel.caretY 67394 }; 67395 67396 var i, len; 67397 67398 if (active.length) { 67399 model.opacity = 1; 67400 67401 var labelColors = []; 67402 var labelTextColors = []; 67403 tooltipPosition = positioners[opts.position].call(me, active, me._eventPosition); 67404 67405 var tooltipItems = []; 67406 for (i = 0, len = active.length; i < len; ++i) { 67407 tooltipItems.push(createTooltipItem(active[i])); 67408 } 67409 67410 // If the user provided a filter function, use it to modify the tooltip items 67411 if (opts.filter) { 67412 tooltipItems = tooltipItems.filter(function(a) { 67413 return opts.filter(a, data); 67414 }); 67415 } 67416 67417 // If the user provided a sorting function, use it to modify the tooltip items 67418 if (opts.itemSort) { 67419 tooltipItems = tooltipItems.sort(function(a, b) { 67420 return opts.itemSort(a, b, data); 67421 }); 67422 } 67423 67424 // Determine colors for boxes 67425 helpers$1.each(tooltipItems, function(tooltipItem) { 67426 labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart)); 67427 labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart)); 67428 }); 67429 67430 67431 // Build the Text Lines 67432 model.title = me.getTitle(tooltipItems, data); 67433 model.beforeBody = me.getBeforeBody(tooltipItems, data); 67434 model.body = me.getBody(tooltipItems, data); 67435 model.afterBody = me.getAfterBody(tooltipItems, data); 67436 model.footer = me.getFooter(tooltipItems, data); 67437 67438 // Initial positioning and colors 67439 model.x = tooltipPosition.x; 67440 model.y = tooltipPosition.y; 67441 model.caretPadding = opts.caretPadding; 67442 model.labelColors = labelColors; 67443 model.labelTextColors = labelTextColors; 67444 67445 // data points 67446 model.dataPoints = tooltipItems; 67447 67448 // We need to determine alignment of the tooltip 67449 tooltipSize = getTooltipSize(this, model); 67450 alignment = determineAlignment(this, tooltipSize); 67451 // Final Size and Position 67452 backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment, me._chart); 67453 } else { 67454 model.opacity = 0; 67455 } 67456 67457 model.xAlign = alignment.xAlign; 67458 model.yAlign = alignment.yAlign; 67459 model.x = backgroundPoint.x; 67460 model.y = backgroundPoint.y; 67461 model.width = tooltipSize.width; 67462 model.height = tooltipSize.height; 67463 67464 // Point where the caret on the tooltip points to 67465 model.caretX = tooltipPosition.x; 67466 model.caretY = tooltipPosition.y; 67467 67468 me._model = model; 67469 67470 if (changed && opts.custom) { 67471 opts.custom.call(me, model); 67472 } 67473 67474 return me; 67475 }, 67476 67477 drawCaret: function(tooltipPoint, size) { 67478 var ctx = this._chart.ctx; 67479 var vm = this._view; 67480 var caretPosition = this.getCaretPosition(tooltipPoint, size, vm); 67481 67482 ctx.lineTo(caretPosition.x1, caretPosition.y1); 67483 ctx.lineTo(caretPosition.x2, caretPosition.y2); 67484 ctx.lineTo(caretPosition.x3, caretPosition.y3); 67485 }, 67486 getCaretPosition: function(tooltipPoint, size, vm) { 67487 var x1, x2, x3, y1, y2, y3; 67488 var caretSize = vm.caretSize; 67489 var cornerRadius = vm.cornerRadius; 67490 var xAlign = vm.xAlign; 67491 var yAlign = vm.yAlign; 67492 var ptX = tooltipPoint.x; 67493 var ptY = tooltipPoint.y; 67494 var width = size.width; 67495 var height = size.height; 67496 67497 if (yAlign === 'center') { 67498 y2 = ptY + (height / 2); 67499 67500 if (xAlign === 'left') { 67501 x1 = ptX; 67502 x2 = x1 - caretSize; 67503 x3 = x1; 67504 67505 y1 = y2 + caretSize; 67506 y3 = y2 - caretSize; 67507 } else { 67508 x1 = ptX + width; 67509 x2 = x1 + caretSize; 67510 x3 = x1; 67511 67512 y1 = y2 - caretSize; 67513 y3 = y2 + caretSize; 67514 } 67515 } else { 67516 if (xAlign === 'left') { 67517 x2 = ptX + cornerRadius + (caretSize); 67518 x1 = x2 - caretSize; 67519 x3 = x2 + caretSize; 67520 } else if (xAlign === 'right') { 67521 x2 = ptX + width - cornerRadius - caretSize; 67522 x1 = x2 - caretSize; 67523 x3 = x2 + caretSize; 67524 } else { 67525 x2 = vm.caretX; 67526 x1 = x2 - caretSize; 67527 x3 = x2 + caretSize; 67528 } 67529 if (yAlign === 'top') { 67530 y1 = ptY; 67531 y2 = y1 - caretSize; 67532 y3 = y1; 67533 } else { 67534 y1 = ptY + height; 67535 y2 = y1 + caretSize; 67536 y3 = y1; 67537 // invert drawing order 67538 var tmp = x3; 67539 x3 = x1; 67540 x1 = tmp; 67541 } 67542 } 67543 return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3}; 67544 }, 67545 67546 drawTitle: function(pt, vm, ctx) { 67547 var title = vm.title; 67548 67549 if (title.length) { 67550 pt.x = getAlignedX(vm, vm._titleAlign); 67551 67552 ctx.textAlign = vm._titleAlign; 67553 ctx.textBaseline = 'top'; 67554 67555 var titleFontSize = vm.titleFontSize; 67556 var titleSpacing = vm.titleSpacing; 67557 67558 ctx.fillStyle = vm.titleFontColor; 67559 ctx.font = helpers$1.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily); 67560 67561 var i, len; 67562 for (i = 0, len = title.length; i < len; ++i) { 67563 ctx.fillText(title[i], pt.x, pt.y); 67564 pt.y += titleFontSize + titleSpacing; // Line Height and spacing 67565 67566 if (i + 1 === title.length) { 67567 pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing 67568 } 67569 } 67570 } 67571 }, 67572 67573 drawBody: function(pt, vm, ctx) { 67574 var bodyFontSize = vm.bodyFontSize; 67575 var bodySpacing = vm.bodySpacing; 67576 var bodyAlign = vm._bodyAlign; 67577 var body = vm.body; 67578 var drawColorBoxes = vm.displayColors; 67579 var labelColors = vm.labelColors; 67580 var xLinePadding = 0; 67581 var colorX = drawColorBoxes ? getAlignedX(vm, 'left') : 0; 67582 var textColor; 67583 67584 ctx.textAlign = bodyAlign; 67585 ctx.textBaseline = 'top'; 67586 ctx.font = helpers$1.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily); 67587 67588 pt.x = getAlignedX(vm, bodyAlign); 67589 67590 // Before Body 67591 var fillLineOfText = function(line) { 67592 ctx.fillText(line, pt.x + xLinePadding, pt.y); 67593 pt.y += bodyFontSize + bodySpacing; 67594 }; 67595 67596 // Before body lines 67597 ctx.fillStyle = vm.bodyFontColor; 67598 helpers$1.each(vm.beforeBody, fillLineOfText); 67599 67600 xLinePadding = drawColorBoxes && bodyAlign !== 'right' 67601 ? bodyAlign === 'center' ? (bodyFontSize / 2 + 1) : (bodyFontSize + 2) 67602 : 0; 67603 67604 // Draw body lines now 67605 helpers$1.each(body, function(bodyItem, i) { 67606 textColor = vm.labelTextColors[i]; 67607 ctx.fillStyle = textColor; 67608 helpers$1.each(bodyItem.before, fillLineOfText); 67609 67610 helpers$1.each(bodyItem.lines, function(line) { 67611 // Draw Legend-like boxes if needed 67612 if (drawColorBoxes) { 67613 // Fill a white rect so that colours merge nicely if the opacity is < 1 67614 ctx.fillStyle = vm.legendColorBackground; 67615 ctx.fillRect(colorX, pt.y, bodyFontSize, bodyFontSize); 67616 67617 // Border 67618 ctx.lineWidth = 1; 67619 ctx.strokeStyle = labelColors[i].borderColor; 67620 ctx.strokeRect(colorX, pt.y, bodyFontSize, bodyFontSize); 67621 67622 // Inner square 67623 ctx.fillStyle = labelColors[i].backgroundColor; 67624 ctx.fillRect(colorX + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2); 67625 ctx.fillStyle = textColor; 67626 } 67627 67628 fillLineOfText(line); 67629 }); 67630 67631 helpers$1.each(bodyItem.after, fillLineOfText); 67632 }); 67633 67634 // Reset back to 0 for after body 67635 xLinePadding = 0; 67636 67637 // After body lines 67638 helpers$1.each(vm.afterBody, fillLineOfText); 67639 pt.y -= bodySpacing; // Remove last body spacing 67640 }, 67641 67642 drawFooter: function(pt, vm, ctx) { 67643 var footer = vm.footer; 67644 67645 if (footer.length) { 67646 pt.x = getAlignedX(vm, vm._footerAlign); 67647 pt.y += vm.footerMarginTop; 67648 67649 ctx.textAlign = vm._footerAlign; 67650 ctx.textBaseline = 'top'; 67651 67652 ctx.fillStyle = vm.footerFontColor; 67653 ctx.font = helpers$1.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily); 67654 67655 helpers$1.each(footer, function(line) { 67656 ctx.fillText(line, pt.x, pt.y); 67657 pt.y += vm.footerFontSize + vm.footerSpacing; 67658 }); 67659 } 67660 }, 67661 67662 drawBackground: function(pt, vm, ctx, tooltipSize) { 67663 ctx.fillStyle = vm.backgroundColor; 67664 ctx.strokeStyle = vm.borderColor; 67665 ctx.lineWidth = vm.borderWidth; 67666 var xAlign = vm.xAlign; 67667 var yAlign = vm.yAlign; 67668 var x = pt.x; 67669 var y = pt.y; 67670 var width = tooltipSize.width; 67671 var height = tooltipSize.height; 67672 var radius = vm.cornerRadius; 67673 67674 ctx.beginPath(); 67675 ctx.moveTo(x + radius, y); 67676 if (yAlign === 'top') { 67677 this.drawCaret(pt, tooltipSize); 67678 } 67679 ctx.lineTo(x + width - radius, y); 67680 ctx.quadraticCurveTo(x + width, y, x + width, y + radius); 67681 if (yAlign === 'center' && xAlign === 'right') { 67682 this.drawCaret(pt, tooltipSize); 67683 } 67684 ctx.lineTo(x + width, y + height - radius); 67685 ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); 67686 if (yAlign === 'bottom') { 67687 this.drawCaret(pt, tooltipSize); 67688 } 67689 ctx.lineTo(x + radius, y + height); 67690 ctx.quadraticCurveTo(x, y + height, x, y + height - radius); 67691 if (yAlign === 'center' && xAlign === 'left') { 67692 this.drawCaret(pt, tooltipSize); 67693 } 67694 ctx.lineTo(x, y + radius); 67695 ctx.quadraticCurveTo(x, y, x + radius, y); 67696 ctx.closePath(); 67697 67698 ctx.fill(); 67699 67700 if (vm.borderWidth > 0) { 67701 ctx.stroke(); 67702 } 67703 }, 67704 67705 draw: function() { 67706 var ctx = this._chart.ctx; 67707 var vm = this._view; 67708 67709 if (vm.opacity === 0) { 67710 return; 67711 } 67712 67713 var tooltipSize = { 67714 width: vm.width, 67715 height: vm.height 67716 }; 67717 var pt = { 67718 x: vm.x, 67719 y: vm.y 67720 }; 67721 67722 // IE11/Edge does not like very small opacities, so snap to 0 67723 var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity; 67724 67725 // Truthy/falsey value for empty tooltip 67726 var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length; 67727 67728 if (this._options.enabled && hasTooltipContent) { 67729 ctx.save(); 67730 ctx.globalAlpha = opacity; 67731 67732 // Draw Background 67733 this.drawBackground(pt, vm, ctx, tooltipSize); 67734 67735 // Draw Title, Body, and Footer 67736 pt.y += vm.yPadding; 67737 67738 // Titles 67739 this.drawTitle(pt, vm, ctx); 67740 67741 // Body 67742 this.drawBody(pt, vm, ctx); 67743 67744 // Footer 67745 this.drawFooter(pt, vm, ctx); 67746 67747 ctx.restore(); 67748 } 67749 }, 67750 67751 /** 67752 * Handle an event 67753 * @private 67754 * @param {IEvent} event - The event to handle 67755 * @returns {boolean} true if the tooltip changed 67756 */ 67757 handleEvent: function(e) { 67758 var me = this; 67759 var options = me._options; 67760 var changed = false; 67761 67762 me._lastActive = me._lastActive || []; 67763 67764 // Find Active Elements for tooltips 67765 if (e.type === 'mouseout') { 67766 me._active = []; 67767 } else { 67768 me._active = me._chart.getElementsAtEventForMode(e, options.mode, options); 67769 } 67770 67771 // Remember Last Actives 67772 changed = !helpers$1.arrayEquals(me._active, me._lastActive); 67773 67774 // Only handle target event on tooltip change 67775 if (changed) { 67776 me._lastActive = me._active; 67777 67778 if (options.enabled || options.custom) { 67779 me._eventPosition = { 67780 x: e.x, 67781 y: e.y 67782 }; 67783 67784 me.update(true); 67785 me.pivot(); 67786 } 67787 } 67788 67789 return changed; 67790 } 67791}); 67792 67793/** 67794 * @namespace Chart.Tooltip.positioners 67795 */ 67796var positioners_1 = positioners; 67797 67798var core_tooltip = exports$3; 67799core_tooltip.positioners = positioners_1; 67800 67801var valueOrDefault$8 = helpers$1.valueOrDefault; 67802 67803core_defaults._set('global', { 67804 elements: {}, 67805 events: [ 67806 'mousemove', 67807 'mouseout', 67808 'click', 67809 'touchstart', 67810 'touchmove' 67811 ], 67812 hover: { 67813 onHover: null, 67814 mode: 'nearest', 67815 intersect: true, 67816 animationDuration: 400 67817 }, 67818 onClick: null, 67819 maintainAspectRatio: true, 67820 responsive: true, 67821 responsiveAnimationDuration: 0 67822}); 67823 67824/** 67825 * Recursively merge the given config objects representing the `scales` option 67826 * by incorporating scale defaults in `xAxes` and `yAxes` array items, then 67827 * returns a deep copy of the result, thus doesn't alter inputs. 67828 */ 67829function mergeScaleConfig(/* config objects ... */) { 67830 return helpers$1.merge({}, [].slice.call(arguments), { 67831 merger: function(key, target, source, options) { 67832 if (key === 'xAxes' || key === 'yAxes') { 67833 var slen = source[key].length; 67834 var i, type, scale; 67835 67836 if (!target[key]) { 67837 target[key] = []; 67838 } 67839 67840 for (i = 0; i < slen; ++i) { 67841 scale = source[key][i]; 67842 type = valueOrDefault$8(scale.type, key === 'xAxes' ? 'category' : 'linear'); 67843 67844 if (i >= target[key].length) { 67845 target[key].push({}); 67846 } 67847 67848 if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) { 67849 // new/untyped scale or type changed: let's apply the new defaults 67850 // then merge source scale to correctly overwrite the defaults. 67851 helpers$1.merge(target[key][i], [core_scaleService.getScaleDefaults(type), scale]); 67852 } else { 67853 // scales type are the same 67854 helpers$1.merge(target[key][i], scale); 67855 } 67856 } 67857 } else { 67858 helpers$1._merger(key, target, source, options); 67859 } 67860 } 67861 }); 67862} 67863 67864/** 67865 * Recursively merge the given config objects as the root options by handling 67866 * default scale options for the `scales` and `scale` properties, then returns 67867 * a deep copy of the result, thus doesn't alter inputs. 67868 */ 67869function mergeConfig(/* config objects ... */) { 67870 return helpers$1.merge({}, [].slice.call(arguments), { 67871 merger: function(key, target, source, options) { 67872 var tval = target[key] || {}; 67873 var sval = source[key]; 67874 67875 if (key === 'scales') { 67876 // scale config merging is complex. Add our own function here for that 67877 target[key] = mergeScaleConfig(tval, sval); 67878 } else if (key === 'scale') { 67879 // used in polar area & radar charts since there is only one scale 67880 target[key] = helpers$1.merge(tval, [core_scaleService.getScaleDefaults(sval.type), sval]); 67881 } else { 67882 helpers$1._merger(key, target, source, options); 67883 } 67884 } 67885 }); 67886} 67887 67888function initConfig(config) { 67889 config = config || {}; 67890 67891 // Do NOT use mergeConfig for the data object because this method merges arrays 67892 // and so would change references to labels and datasets, preventing data updates. 67893 var data = config.data = config.data || {}; 67894 data.datasets = data.datasets || []; 67895 data.labels = data.labels || []; 67896 67897 config.options = mergeConfig( 67898 core_defaults.global, 67899 core_defaults[config.type], 67900 config.options || {}); 67901 67902 return config; 67903} 67904 67905function updateConfig(chart) { 67906 var newOptions = chart.options; 67907 67908 helpers$1.each(chart.scales, function(scale) { 67909 core_layouts.removeBox(chart, scale); 67910 }); 67911 67912 newOptions = mergeConfig( 67913 core_defaults.global, 67914 core_defaults[chart.config.type], 67915 newOptions); 67916 67917 chart.options = chart.config.options = newOptions; 67918 chart.ensureScalesHaveIDs(); 67919 chart.buildOrUpdateScales(); 67920 67921 // Tooltip 67922 chart.tooltip._options = newOptions.tooltips; 67923 chart.tooltip.initialize(); 67924} 67925 67926function positionIsHorizontal(position) { 67927 return position === 'top' || position === 'bottom'; 67928} 67929 67930var Chart = function(item, config) { 67931 this.construct(item, config); 67932 return this; 67933}; 67934 67935helpers$1.extend(Chart.prototype, /** @lends Chart */ { 67936 /** 67937 * @private 67938 */ 67939 construct: function(item, config) { 67940 var me = this; 67941 67942 config = initConfig(config); 67943 67944 var context = platform.acquireContext(item, config); 67945 var canvas = context && context.canvas; 67946 var height = canvas && canvas.height; 67947 var width = canvas && canvas.width; 67948 67949 me.id = helpers$1.uid(); 67950 me.ctx = context; 67951 me.canvas = canvas; 67952 me.config = config; 67953 me.width = width; 67954 me.height = height; 67955 me.aspectRatio = height ? width / height : null; 67956 me.options = config.options; 67957 me._bufferedRender = false; 67958 67959 /** 67960 * Provided for backward compatibility, Chart and Chart.Controller have been merged, 67961 * the "instance" still need to be defined since it might be called from plugins. 67962 * @prop Chart#chart 67963 * @deprecated since version 2.6.0 67964 * @todo remove at version 3 67965 * @private 67966 */ 67967 me.chart = me; 67968 me.controller = me; // chart.chart.controller #inception 67969 67970 // Add the chart instance to the global namespace 67971 Chart.instances[me.id] = me; 67972 67973 // Define alias to the config data: `chart.data === chart.config.data` 67974 Object.defineProperty(me, 'data', { 67975 get: function() { 67976 return me.config.data; 67977 }, 67978 set: function(value) { 67979 me.config.data = value; 67980 } 67981 }); 67982 67983 if (!context || !canvas) { 67984 // The given item is not a compatible context2d element, let's return before finalizing 67985 // the chart initialization but after setting basic chart / controller properties that 67986 // can help to figure out that the chart is not valid (e.g chart.canvas !== null); 67987 // https://github.com/chartjs/Chart.js/issues/2807 67988 console.error("Failed to create chart: can't acquire context from the given item"); 67989 return; 67990 } 67991 67992 me.initialize(); 67993 me.update(); 67994 }, 67995 67996 /** 67997 * @private 67998 */ 67999 initialize: function() { 68000 var me = this; 68001 68002 // Before init plugin notification 68003 core_plugins.notify(me, 'beforeInit'); 68004 68005 helpers$1.retinaScale(me, me.options.devicePixelRatio); 68006 68007 me.bindEvents(); 68008 68009 if (me.options.responsive) { 68010 // Initial resize before chart draws (must be silent to preserve initial animations). 68011 me.resize(true); 68012 } 68013 68014 // Make sure scales have IDs and are built before we build any controllers. 68015 me.ensureScalesHaveIDs(); 68016 me.buildOrUpdateScales(); 68017 me.initToolTip(); 68018 68019 // After init plugin notification 68020 core_plugins.notify(me, 'afterInit'); 68021 68022 return me; 68023 }, 68024 68025 clear: function() { 68026 helpers$1.canvas.clear(this); 68027 return this; 68028 }, 68029 68030 stop: function() { 68031 // Stops any current animation loop occurring 68032 core_animations.cancelAnimation(this); 68033 return this; 68034 }, 68035 68036 resize: function(silent) { 68037 var me = this; 68038 var options = me.options; 68039 var canvas = me.canvas; 68040 var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null; 68041 68042 // the canvas render width and height will be casted to integers so make sure that 68043 // the canvas display style uses the same integer values to avoid blurring effect. 68044 68045 // Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed 68046 var newWidth = Math.max(0, Math.floor(helpers$1.getMaximumWidth(canvas))); 68047 var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers$1.getMaximumHeight(canvas))); 68048 68049 if (me.width === newWidth && me.height === newHeight) { 68050 return; 68051 } 68052 68053 canvas.width = me.width = newWidth; 68054 canvas.height = me.height = newHeight; 68055 canvas.style.width = newWidth + 'px'; 68056 canvas.style.height = newHeight + 'px'; 68057 68058 helpers$1.retinaScale(me, options.devicePixelRatio); 68059 68060 if (!silent) { 68061 // Notify any plugins about the resize 68062 var newSize = {width: newWidth, height: newHeight}; 68063 core_plugins.notify(me, 'resize', [newSize]); 68064 68065 // Notify of resize 68066 if (options.onResize) { 68067 options.onResize(me, newSize); 68068 } 68069 68070 me.stop(); 68071 me.update({ 68072 duration: options.responsiveAnimationDuration 68073 }); 68074 } 68075 }, 68076 68077 ensureScalesHaveIDs: function() { 68078 var options = this.options; 68079 var scalesOptions = options.scales || {}; 68080 var scaleOptions = options.scale; 68081 68082 helpers$1.each(scalesOptions.xAxes, function(xAxisOptions, index) { 68083 xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); 68084 }); 68085 68086 helpers$1.each(scalesOptions.yAxes, function(yAxisOptions, index) { 68087 yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); 68088 }); 68089 68090 if (scaleOptions) { 68091 scaleOptions.id = scaleOptions.id || 'scale'; 68092 } 68093 }, 68094 68095 /** 68096 * Builds a map of scale ID to scale object for future lookup. 68097 */ 68098 buildOrUpdateScales: function() { 68099 var me = this; 68100 var options = me.options; 68101 var scales = me.scales || {}; 68102 var items = []; 68103 var updated = Object.keys(scales).reduce(function(obj, id) { 68104 obj[id] = false; 68105 return obj; 68106 }, {}); 68107 68108 if (options.scales) { 68109 items = items.concat( 68110 (options.scales.xAxes || []).map(function(xAxisOptions) { 68111 return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'}; 68112 }), 68113 (options.scales.yAxes || []).map(function(yAxisOptions) { 68114 return {options: yAxisOptions, dtype: 'linear', dposition: 'left'}; 68115 }) 68116 ); 68117 } 68118 68119 if (options.scale) { 68120 items.push({ 68121 options: options.scale, 68122 dtype: 'radialLinear', 68123 isDefault: true, 68124 dposition: 'chartArea' 68125 }); 68126 } 68127 68128 helpers$1.each(items, function(item) { 68129 var scaleOptions = item.options; 68130 var id = scaleOptions.id; 68131 var scaleType = valueOrDefault$8(scaleOptions.type, item.dtype); 68132 68133 if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) { 68134 scaleOptions.position = item.dposition; 68135 } 68136 68137 updated[id] = true; 68138 var scale = null; 68139 if (id in scales && scales[id].type === scaleType) { 68140 scale = scales[id]; 68141 scale.options = scaleOptions; 68142 scale.ctx = me.ctx; 68143 scale.chart = me; 68144 } else { 68145 var scaleClass = core_scaleService.getScaleConstructor(scaleType); 68146 if (!scaleClass) { 68147 return; 68148 } 68149 scale = new scaleClass({ 68150 id: id, 68151 type: scaleType, 68152 options: scaleOptions, 68153 ctx: me.ctx, 68154 chart: me 68155 }); 68156 scales[scale.id] = scale; 68157 } 68158 68159 scale.mergeTicksOptions(); 68160 68161 // TODO(SB): I think we should be able to remove this custom case (options.scale) 68162 // and consider it as a regular scale part of the "scales"" map only! This would 68163 // make the logic easier and remove some useless? custom code. 68164 if (item.isDefault) { 68165 me.scale = scale; 68166 } 68167 }); 68168 // clear up discarded scales 68169 helpers$1.each(updated, function(hasUpdated, id) { 68170 if (!hasUpdated) { 68171 delete scales[id]; 68172 } 68173 }); 68174 68175 me.scales = scales; 68176 68177 core_scaleService.addScalesToLayout(this); 68178 }, 68179 68180 buildOrUpdateControllers: function() { 68181 var me = this; 68182 var newControllers = []; 68183 68184 helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { 68185 var meta = me.getDatasetMeta(datasetIndex); 68186 var type = dataset.type || me.config.type; 68187 68188 if (meta.type && meta.type !== type) { 68189 me.destroyDatasetMeta(datasetIndex); 68190 meta = me.getDatasetMeta(datasetIndex); 68191 } 68192 meta.type = type; 68193 68194 if (meta.controller) { 68195 meta.controller.updateIndex(datasetIndex); 68196 meta.controller.linkScales(); 68197 } else { 68198 var ControllerClass = controllers[meta.type]; 68199 if (ControllerClass === undefined) { 68200 throw new Error('"' + meta.type + '" is not a chart type.'); 68201 } 68202 68203 meta.controller = new ControllerClass(me, datasetIndex); 68204 newControllers.push(meta.controller); 68205 } 68206 }, me); 68207 68208 return newControllers; 68209 }, 68210 68211 /** 68212 * Reset the elements of all datasets 68213 * @private 68214 */ 68215 resetElements: function() { 68216 var me = this; 68217 helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { 68218 me.getDatasetMeta(datasetIndex).controller.reset(); 68219 }, me); 68220 }, 68221 68222 /** 68223 * Resets the chart back to it's state before the initial animation 68224 */ 68225 reset: function() { 68226 this.resetElements(); 68227 this.tooltip.initialize(); 68228 }, 68229 68230 update: function(config) { 68231 var me = this; 68232 68233 if (!config || typeof config !== 'object') { 68234 // backwards compatibility 68235 config = { 68236 duration: config, 68237 lazy: arguments[1] 68238 }; 68239 } 68240 68241 updateConfig(me); 68242 68243 // plugins options references might have change, let's invalidate the cache 68244 // https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167 68245 core_plugins._invalidate(me); 68246 68247 if (core_plugins.notify(me, 'beforeUpdate') === false) { 68248 return; 68249 } 68250 68251 // In case the entire data object changed 68252 me.tooltip._data = me.data; 68253 68254 // Make sure dataset controllers are updated and new controllers are reset 68255 var newControllers = me.buildOrUpdateControllers(); 68256 68257 // Make sure all dataset controllers have correct meta data counts 68258 helpers$1.each(me.data.datasets, function(dataset, datasetIndex) { 68259 me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); 68260 }, me); 68261 68262 me.updateLayout(); 68263 68264 // Can only reset the new controllers after the scales have been updated 68265 if (me.options.animation && me.options.animation.duration) { 68266 helpers$1.each(newControllers, function(controller) { 68267 controller.reset(); 68268 }); 68269 } 68270 68271 me.updateDatasets(); 68272 68273 // Need to reset tooltip in case it is displayed with elements that are removed 68274 // after update. 68275 me.tooltip.initialize(); 68276 68277 // Last active contains items that were previously in the tooltip. 68278 // When we reset the tooltip, we need to clear it 68279 me.lastActive = []; 68280 68281 // Do this before render so that any plugins that need final scale updates can use it 68282 core_plugins.notify(me, 'afterUpdate'); 68283 68284 if (me._bufferedRender) { 68285 me._bufferedRequest = { 68286 duration: config.duration, 68287 easing: config.easing, 68288 lazy: config.lazy 68289 }; 68290 } else { 68291 me.render(config); 68292 } 68293 }, 68294 68295 /** 68296 * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` 68297 * hook, in which case, plugins will not be called on `afterLayout`. 68298 * @private 68299 */ 68300 updateLayout: function() { 68301 var me = this; 68302 68303 if (core_plugins.notify(me, 'beforeLayout') === false) { 68304 return; 68305 } 68306 68307 core_layouts.update(this, this.width, this.height); 68308 68309 /** 68310 * Provided for backward compatibility, use `afterLayout` instead. 68311 * @method IPlugin#afterScaleUpdate 68312 * @deprecated since version 2.5.0 68313 * @todo remove at version 3 68314 * @private 68315 */ 68316 core_plugins.notify(me, 'afterScaleUpdate'); 68317 core_plugins.notify(me, 'afterLayout'); 68318 }, 68319 68320 /** 68321 * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` 68322 * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. 68323 * @private 68324 */ 68325 updateDatasets: function() { 68326 var me = this; 68327 68328 if (core_plugins.notify(me, 'beforeDatasetsUpdate') === false) { 68329 return; 68330 } 68331 68332 for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { 68333 me.updateDataset(i); 68334 } 68335 68336 core_plugins.notify(me, 'afterDatasetsUpdate'); 68337 }, 68338 68339 /** 68340 * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate` 68341 * hook, in which case, plugins will not be called on `afterDatasetUpdate`. 68342 * @private 68343 */ 68344 updateDataset: function(index) { 68345 var me = this; 68346 var meta = me.getDatasetMeta(index); 68347 var args = { 68348 meta: meta, 68349 index: index 68350 }; 68351 68352 if (core_plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) { 68353 return; 68354 } 68355 68356 meta.controller.update(); 68357 68358 core_plugins.notify(me, 'afterDatasetUpdate', [args]); 68359 }, 68360 68361 render: function(config) { 68362 var me = this; 68363 68364 if (!config || typeof config !== 'object') { 68365 // backwards compatibility 68366 config = { 68367 duration: config, 68368 lazy: arguments[1] 68369 }; 68370 } 68371 68372 var animationOptions = me.options.animation; 68373 var duration = valueOrDefault$8(config.duration, animationOptions && animationOptions.duration); 68374 var lazy = config.lazy; 68375 68376 if (core_plugins.notify(me, 'beforeRender') === false) { 68377 return; 68378 } 68379 68380 var onComplete = function(animation) { 68381 core_plugins.notify(me, 'afterRender'); 68382 helpers$1.callback(animationOptions && animationOptions.onComplete, [animation], me); 68383 }; 68384 68385 if (animationOptions && duration) { 68386 var animation = new core_animation({ 68387 numSteps: duration / 16.66, // 60 fps 68388 easing: config.easing || animationOptions.easing, 68389 68390 render: function(chart, animationObject) { 68391 var easingFunction = helpers$1.easing.effects[animationObject.easing]; 68392 var currentStep = animationObject.currentStep; 68393 var stepDecimal = currentStep / animationObject.numSteps; 68394 68395 chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep); 68396 }, 68397 68398 onAnimationProgress: animationOptions.onProgress, 68399 onAnimationComplete: onComplete 68400 }); 68401 68402 core_animations.addAnimation(me, animation, duration, lazy); 68403 } else { 68404 me.draw(); 68405 68406 // See https://github.com/chartjs/Chart.js/issues/3781 68407 onComplete(new core_animation({numSteps: 0, chart: me})); 68408 } 68409 68410 return me; 68411 }, 68412 68413 draw: function(easingValue) { 68414 var me = this; 68415 68416 me.clear(); 68417 68418 if (helpers$1.isNullOrUndef(easingValue)) { 68419 easingValue = 1; 68420 } 68421 68422 me.transition(easingValue); 68423 68424 if (me.width <= 0 || me.height <= 0) { 68425 return; 68426 } 68427 68428 if (core_plugins.notify(me, 'beforeDraw', [easingValue]) === false) { 68429 return; 68430 } 68431 68432 // Draw all the scales 68433 helpers$1.each(me.boxes, function(box) { 68434 box.draw(me.chartArea); 68435 }, me); 68436 68437 me.drawDatasets(easingValue); 68438 me._drawTooltip(easingValue); 68439 68440 core_plugins.notify(me, 'afterDraw', [easingValue]); 68441 }, 68442 68443 /** 68444 * @private 68445 */ 68446 transition: function(easingValue) { 68447 var me = this; 68448 68449 for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) { 68450 if (me.isDatasetVisible(i)) { 68451 me.getDatasetMeta(i).controller.transition(easingValue); 68452 } 68453 } 68454 68455 me.tooltip.transition(easingValue); 68456 }, 68457 68458 /** 68459 * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` 68460 * hook, in which case, plugins will not be called on `afterDatasetsDraw`. 68461 * @private 68462 */ 68463 drawDatasets: function(easingValue) { 68464 var me = this; 68465 68466 if (core_plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { 68467 return; 68468 } 68469 68470 // Draw datasets reversed to support proper line stacking 68471 for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) { 68472 if (me.isDatasetVisible(i)) { 68473 me.drawDataset(i, easingValue); 68474 } 68475 } 68476 68477 core_plugins.notify(me, 'afterDatasetsDraw', [easingValue]); 68478 }, 68479 68480 /** 68481 * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw` 68482 * hook, in which case, plugins will not be called on `afterDatasetDraw`. 68483 * @private 68484 */ 68485 drawDataset: function(index, easingValue) { 68486 var me = this; 68487 var meta = me.getDatasetMeta(index); 68488 var args = { 68489 meta: meta, 68490 index: index, 68491 easingValue: easingValue 68492 }; 68493 68494 if (core_plugins.notify(me, 'beforeDatasetDraw', [args]) === false) { 68495 return; 68496 } 68497 68498 meta.controller.draw(easingValue); 68499 68500 core_plugins.notify(me, 'afterDatasetDraw', [args]); 68501 }, 68502 68503 /** 68504 * Draws tooltip unless a plugin returns `false` to the `beforeTooltipDraw` 68505 * hook, in which case, plugins will not be called on `afterTooltipDraw`. 68506 * @private 68507 */ 68508 _drawTooltip: function(easingValue) { 68509 var me = this; 68510 var tooltip = me.tooltip; 68511 var args = { 68512 tooltip: tooltip, 68513 easingValue: easingValue 68514 }; 68515 68516 if (core_plugins.notify(me, 'beforeTooltipDraw', [args]) === false) { 68517 return; 68518 } 68519 68520 tooltip.draw(); 68521 68522 core_plugins.notify(me, 'afterTooltipDraw', [args]); 68523 }, 68524 68525 /** 68526 * Get the single element that was clicked on 68527 * @return An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw 68528 */ 68529 getElementAtEvent: function(e) { 68530 return core_interaction.modes.single(this, e); 68531 }, 68532 68533 getElementsAtEvent: function(e) { 68534 return core_interaction.modes.label(this, e, {intersect: true}); 68535 }, 68536 68537 getElementsAtXAxis: function(e) { 68538 return core_interaction.modes['x-axis'](this, e, {intersect: true}); 68539 }, 68540 68541 getElementsAtEventForMode: function(e, mode, options) { 68542 var method = core_interaction.modes[mode]; 68543 if (typeof method === 'function') { 68544 return method(this, e, options); 68545 } 68546 68547 return []; 68548 }, 68549 68550 getDatasetAtEvent: function(e) { 68551 return core_interaction.modes.dataset(this, e, {intersect: true}); 68552 }, 68553 68554 getDatasetMeta: function(datasetIndex) { 68555 var me = this; 68556 var dataset = me.data.datasets[datasetIndex]; 68557 if (!dataset._meta) { 68558 dataset._meta = {}; 68559 } 68560 68561 var meta = dataset._meta[me.id]; 68562 if (!meta) { 68563 meta = dataset._meta[me.id] = { 68564 type: null, 68565 data: [], 68566 dataset: null, 68567 controller: null, 68568 hidden: null, // See isDatasetVisible() comment 68569 xAxisID: null, 68570 yAxisID: null 68571 }; 68572 } 68573 68574 return meta; 68575 }, 68576 68577 getVisibleDatasetCount: function() { 68578 var count = 0; 68579 for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) { 68580 if (this.isDatasetVisible(i)) { 68581 count++; 68582 } 68583 } 68584 return count; 68585 }, 68586 68587 isDatasetVisible: function(datasetIndex) { 68588 var meta = this.getDatasetMeta(datasetIndex); 68589 68590 // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, 68591 // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. 68592 return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden; 68593 }, 68594 68595 generateLegend: function() { 68596 return this.options.legendCallback(this); 68597 }, 68598 68599 /** 68600 * @private 68601 */ 68602 destroyDatasetMeta: function(datasetIndex) { 68603 var id = this.id; 68604 var dataset = this.data.datasets[datasetIndex]; 68605 var meta = dataset._meta && dataset._meta[id]; 68606 68607 if (meta) { 68608 meta.controller.destroy(); 68609 delete dataset._meta[id]; 68610 } 68611 }, 68612 68613 destroy: function() { 68614 var me = this; 68615 var canvas = me.canvas; 68616 var i, ilen; 68617 68618 me.stop(); 68619 68620 // dataset controllers need to cleanup associated data 68621 for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { 68622 me.destroyDatasetMeta(i); 68623 } 68624 68625 if (canvas) { 68626 me.unbindEvents(); 68627 helpers$1.canvas.clear(me); 68628 platform.releaseContext(me.ctx); 68629 me.canvas = null; 68630 me.ctx = null; 68631 } 68632 68633 core_plugins.notify(me, 'destroy'); 68634 68635 delete Chart.instances[me.id]; 68636 }, 68637 68638 toBase64Image: function() { 68639 return this.canvas.toDataURL.apply(this.canvas, arguments); 68640 }, 68641 68642 initToolTip: function() { 68643 var me = this; 68644 me.tooltip = new core_tooltip({ 68645 _chart: me, 68646 _chartInstance: me, // deprecated, backward compatibility 68647 _data: me.data, 68648 _options: me.options.tooltips 68649 }, me); 68650 }, 68651 68652 /** 68653 * @private 68654 */ 68655 bindEvents: function() { 68656 var me = this; 68657 var listeners = me._listeners = {}; 68658 var listener = function() { 68659 me.eventHandler.apply(me, arguments); 68660 }; 68661 68662 helpers$1.each(me.options.events, function(type) { 68663 platform.addEventListener(me, type, listener); 68664 listeners[type] = listener; 68665 }); 68666 68667 // Elements used to detect size change should not be injected for non responsive charts. 68668 // See https://github.com/chartjs/Chart.js/issues/2210 68669 if (me.options.responsive) { 68670 listener = function() { 68671 me.resize(); 68672 }; 68673 68674 platform.addEventListener(me, 'resize', listener); 68675 listeners.resize = listener; 68676 } 68677 }, 68678 68679 /** 68680 * @private 68681 */ 68682 unbindEvents: function() { 68683 var me = this; 68684 var listeners = me._listeners; 68685 if (!listeners) { 68686 return; 68687 } 68688 68689 delete me._listeners; 68690 helpers$1.each(listeners, function(listener, type) { 68691 platform.removeEventListener(me, type, listener); 68692 }); 68693 }, 68694 68695 updateHoverStyle: function(elements, mode, enabled) { 68696 var method = enabled ? 'setHoverStyle' : 'removeHoverStyle'; 68697 var element, i, ilen; 68698 68699 for (i = 0, ilen = elements.length; i < ilen; ++i) { 68700 element = elements[i]; 68701 if (element) { 68702 this.getDatasetMeta(element._datasetIndex).controller[method](element); 68703 } 68704 } 68705 }, 68706 68707 /** 68708 * @private 68709 */ 68710 eventHandler: function(e) { 68711 var me = this; 68712 var tooltip = me.tooltip; 68713 68714 if (core_plugins.notify(me, 'beforeEvent', [e]) === false) { 68715 return; 68716 } 68717 68718 // Buffer any update calls so that renders do not occur 68719 me._bufferedRender = true; 68720 me._bufferedRequest = null; 68721 68722 var changed = me.handleEvent(e); 68723 // for smooth tooltip animations issue #4989 68724 // the tooltip should be the source of change 68725 // Animation check workaround: 68726 // tooltip._start will be null when tooltip isn't animating 68727 if (tooltip) { 68728 changed = tooltip._start 68729 ? tooltip.handleEvent(e) 68730 : changed | tooltip.handleEvent(e); 68731 } 68732 68733 core_plugins.notify(me, 'afterEvent', [e]); 68734 68735 var bufferedRequest = me._bufferedRequest; 68736 if (bufferedRequest) { 68737 // If we have an update that was triggered, we need to do a normal render 68738 me.render(bufferedRequest); 68739 } else if (changed && !me.animating) { 68740 // If entering, leaving, or changing elements, animate the change via pivot 68741 me.stop(); 68742 68743 // We only need to render at this point. Updating will cause scales to be 68744 // recomputed generating flicker & using more memory than necessary. 68745 me.render({ 68746 duration: me.options.hover.animationDuration, 68747 lazy: true 68748 }); 68749 } 68750 68751 me._bufferedRender = false; 68752 me._bufferedRequest = null; 68753 68754 return me; 68755 }, 68756 68757 /** 68758 * Handle an event 68759 * @private 68760 * @param {IEvent} event the event to handle 68761 * @return {boolean} true if the chart needs to re-render 68762 */ 68763 handleEvent: function(e) { 68764 var me = this; 68765 var options = me.options || {}; 68766 var hoverOptions = options.hover; 68767 var changed = false; 68768 68769 me.lastActive = me.lastActive || []; 68770 68771 // Find Active Elements for hover and tooltips 68772 if (e.type === 'mouseout') { 68773 me.active = []; 68774 } else { 68775 me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); 68776 } 68777 68778 // Invoke onHover hook 68779 // Need to call with native event here to not break backwards compatibility 68780 helpers$1.callback(options.onHover || options.hover.onHover, [e.native, me.active], me); 68781 68782 if (e.type === 'mouseup' || e.type === 'click') { 68783 if (options.onClick) { 68784 // Use e.native here for backwards compatibility 68785 options.onClick.call(me, e.native, me.active); 68786 } 68787 } 68788 68789 // Remove styling for last active (even if it may still be active) 68790 if (me.lastActive.length) { 68791 me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); 68792 } 68793 68794 // Built in hover styling 68795 if (me.active.length && hoverOptions.mode) { 68796 me.updateHoverStyle(me.active, hoverOptions.mode, true); 68797 } 68798 68799 changed = !helpers$1.arrayEquals(me.active, me.lastActive); 68800 68801 // Remember Last Actives 68802 me.lastActive = me.active; 68803 68804 return changed; 68805 } 68806}); 68807 68808/** 68809 * NOTE(SB) We actually don't use this container anymore but we need to keep it 68810 * for backward compatibility. Though, it can still be useful for plugins that 68811 * would need to work on multiple charts?! 68812 */ 68813Chart.instances = {}; 68814 68815var core_controller = Chart; 68816 68817// DEPRECATIONS 68818 68819/** 68820 * Provided for backward compatibility, use Chart instead. 68821 * @class Chart.Controller 68822 * @deprecated since version 2.6 68823 * @todo remove at version 3 68824 * @private 68825 */ 68826Chart.Controller = Chart; 68827 68828/** 68829 * Provided for backward compatibility, not available anymore. 68830 * @namespace Chart 68831 * @deprecated since version 2.8 68832 * @todo remove at version 3 68833 * @private 68834 */ 68835Chart.types = {}; 68836 68837/** 68838 * Provided for backward compatibility, not available anymore. 68839 * @namespace Chart.helpers.configMerge 68840 * @deprecated since version 2.8.0 68841 * @todo remove at version 3 68842 * @private 68843 */ 68844helpers$1.configMerge = mergeConfig; 68845 68846/** 68847 * Provided for backward compatibility, not available anymore. 68848 * @namespace Chart.helpers.scaleMerge 68849 * @deprecated since version 2.8.0 68850 * @todo remove at version 3 68851 * @private 68852 */ 68853helpers$1.scaleMerge = mergeScaleConfig; 68854 68855var core_helpers = function() { 68856 68857 // -- Basic js utility methods 68858 68859 helpers$1.where = function(collection, filterCallback) { 68860 if (helpers$1.isArray(collection) && Array.prototype.filter) { 68861 return collection.filter(filterCallback); 68862 } 68863 var filtered = []; 68864 68865 helpers$1.each(collection, function(item) { 68866 if (filterCallback(item)) { 68867 filtered.push(item); 68868 } 68869 }); 68870 68871 return filtered; 68872 }; 68873 helpers$1.findIndex = Array.prototype.findIndex ? 68874 function(array, callback, scope) { 68875 return array.findIndex(callback, scope); 68876 } : 68877 function(array, callback, scope) { 68878 scope = scope === undefined ? array : scope; 68879 for (var i = 0, ilen = array.length; i < ilen; ++i) { 68880 if (callback.call(scope, array[i], i, array)) { 68881 return i; 68882 } 68883 } 68884 return -1; 68885 }; 68886 helpers$1.findNextWhere = function(arrayToSearch, filterCallback, startIndex) { 68887 // Default to start of the array 68888 if (helpers$1.isNullOrUndef(startIndex)) { 68889 startIndex = -1; 68890 } 68891 for (var i = startIndex + 1; i < arrayToSearch.length; i++) { 68892 var currentItem = arrayToSearch[i]; 68893 if (filterCallback(currentItem)) { 68894 return currentItem; 68895 } 68896 } 68897 }; 68898 helpers$1.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) { 68899 // Default to end of the array 68900 if (helpers$1.isNullOrUndef(startIndex)) { 68901 startIndex = arrayToSearch.length; 68902 } 68903 for (var i = startIndex - 1; i >= 0; i--) { 68904 var currentItem = arrayToSearch[i]; 68905 if (filterCallback(currentItem)) { 68906 return currentItem; 68907 } 68908 } 68909 }; 68910 68911 // -- Math methods 68912 helpers$1.isNumber = function(n) { 68913 return !isNaN(parseFloat(n)) && isFinite(n); 68914 }; 68915 helpers$1.almostEquals = function(x, y, epsilon) { 68916 return Math.abs(x - y) < epsilon; 68917 }; 68918 helpers$1.almostWhole = function(x, epsilon) { 68919 var rounded = Math.round(x); 68920 return (((rounded - epsilon) < x) && ((rounded + epsilon) > x)); 68921 }; 68922 helpers$1.max = function(array) { 68923 return array.reduce(function(max, value) { 68924 if (!isNaN(value)) { 68925 return Math.max(max, value); 68926 } 68927 return max; 68928 }, Number.NEGATIVE_INFINITY); 68929 }; 68930 helpers$1.min = function(array) { 68931 return array.reduce(function(min, value) { 68932 if (!isNaN(value)) { 68933 return Math.min(min, value); 68934 } 68935 return min; 68936 }, Number.POSITIVE_INFINITY); 68937 }; 68938 helpers$1.sign = Math.sign ? 68939 function(x) { 68940 return Math.sign(x); 68941 } : 68942 function(x) { 68943 x = +x; // convert to a number 68944 if (x === 0 || isNaN(x)) { 68945 return x; 68946 } 68947 return x > 0 ? 1 : -1; 68948 }; 68949 helpers$1.log10 = Math.log10 ? 68950 function(x) { 68951 return Math.log10(x); 68952 } : 68953 function(x) { 68954 var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10. 68955 // Check for whole powers of 10, 68956 // which due to floating point rounding error should be corrected. 68957 var powerOf10 = Math.round(exponent); 68958 var isPowerOf10 = x === Math.pow(10, powerOf10); 68959 68960 return isPowerOf10 ? powerOf10 : exponent; 68961 }; 68962 helpers$1.toRadians = function(degrees) { 68963 return degrees * (Math.PI / 180); 68964 }; 68965 helpers$1.toDegrees = function(radians) { 68966 return radians * (180 / Math.PI); 68967 }; 68968 68969 /** 68970 * Returns the number of decimal places 68971 * i.e. the number of digits after the decimal point, of the value of this Number. 68972 * @param {number} x - A number. 68973 * @returns {number} The number of decimal places. 68974 * @private 68975 */ 68976 helpers$1._decimalPlaces = function(x) { 68977 if (!helpers$1.isFinite(x)) { 68978 return; 68979 } 68980 var e = 1; 68981 var p = 0; 68982 while (Math.round(x * e) / e !== x) { 68983 e *= 10; 68984 p++; 68985 } 68986 return p; 68987 }; 68988 68989 // Gets the angle from vertical upright to the point about a centre. 68990 helpers$1.getAngleFromPoint = function(centrePoint, anglePoint) { 68991 var distanceFromXCenter = anglePoint.x - centrePoint.x; 68992 var distanceFromYCenter = anglePoint.y - centrePoint.y; 68993 var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); 68994 68995 var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); 68996 68997 if (angle < (-0.5 * Math.PI)) { 68998 angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2] 68999 } 69000 69001 return { 69002 angle: angle, 69003 distance: radialDistanceFromCenter 69004 }; 69005 }; 69006 helpers$1.distanceBetweenPoints = function(pt1, pt2) { 69007 return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); 69008 }; 69009 69010 /** 69011 * Provided for backward compatibility, not available anymore 69012 * @function Chart.helpers.aliasPixel 69013 * @deprecated since version 2.8.0 69014 * @todo remove at version 3 69015 */ 69016 helpers$1.aliasPixel = function(pixelWidth) { 69017 return (pixelWidth % 2 === 0) ? 0 : 0.5; 69018 }; 69019 69020 /** 69021 * Returns the aligned pixel value to avoid anti-aliasing blur 69022 * @param {Chart} chart - The chart instance. 69023 * @param {number} pixel - A pixel value. 69024 * @param {number} width - The width of the element. 69025 * @returns {number} The aligned pixel value. 69026 * @private 69027 */ 69028 helpers$1._alignPixel = function(chart, pixel, width) { 69029 var devicePixelRatio = chart.currentDevicePixelRatio; 69030 var halfWidth = width / 2; 69031 return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth; 69032 }; 69033 69034 helpers$1.splineCurve = function(firstPoint, middlePoint, afterPoint, t) { 69035 // Props to Rob Spencer at scaled innovation for his post on splining between points 69036 // http://scaledinnovation.com/analytics/splines/aboutSplines.html 69037 69038 // This function must also respect "skipped" points 69039 69040 var previous = firstPoint.skip ? middlePoint : firstPoint; 69041 var current = middlePoint; 69042 var next = afterPoint.skip ? middlePoint : afterPoint; 69043 69044 var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)); 69045 var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)); 69046 69047 var s01 = d01 / (d01 + d12); 69048 var s12 = d12 / (d01 + d12); 69049 69050 // If all points are the same, s01 & s02 will be inf 69051 s01 = isNaN(s01) ? 0 : s01; 69052 s12 = isNaN(s12) ? 0 : s12; 69053 69054 var fa = t * s01; // scaling factor for triangle Ta 69055 var fb = t * s12; 69056 69057 return { 69058 previous: { 69059 x: current.x - fa * (next.x - previous.x), 69060 y: current.y - fa * (next.y - previous.y) 69061 }, 69062 next: { 69063 x: current.x + fb * (next.x - previous.x), 69064 y: current.y + fb * (next.y - previous.y) 69065 } 69066 }; 69067 }; 69068 helpers$1.EPSILON = Number.EPSILON || 1e-14; 69069 helpers$1.splineCurveMonotone = function(points) { 69070 // This function calculates Bézier control points in a similar way than |splineCurve|, 69071 // but preserves monotonicity of the provided data and ensures no local extremums are added 69072 // between the dataset discrete points due to the interpolation. 69073 // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation 69074 69075 var pointsWithTangents = (points || []).map(function(point) { 69076 return { 69077 model: point._model, 69078 deltaK: 0, 69079 mK: 0 69080 }; 69081 }); 69082 69083 // Calculate slopes (deltaK) and initialize tangents (mK) 69084 var pointsLen = pointsWithTangents.length; 69085 var i, pointBefore, pointCurrent, pointAfter; 69086 for (i = 0; i < pointsLen; ++i) { 69087 pointCurrent = pointsWithTangents[i]; 69088 if (pointCurrent.model.skip) { 69089 continue; 69090 } 69091 69092 pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; 69093 pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; 69094 if (pointAfter && !pointAfter.model.skip) { 69095 var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x); 69096 69097 // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 69098 pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0; 69099 } 69100 69101 if (!pointBefore || pointBefore.model.skip) { 69102 pointCurrent.mK = pointCurrent.deltaK; 69103 } else if (!pointAfter || pointAfter.model.skip) { 69104 pointCurrent.mK = pointBefore.deltaK; 69105 } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) { 69106 pointCurrent.mK = 0; 69107 } else { 69108 pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2; 69109 } 69110 } 69111 69112 // Adjust tangents to ensure monotonic properties 69113 var alphaK, betaK, tauK, squaredMagnitude; 69114 for (i = 0; i < pointsLen - 1; ++i) { 69115 pointCurrent = pointsWithTangents[i]; 69116 pointAfter = pointsWithTangents[i + 1]; 69117 if (pointCurrent.model.skip || pointAfter.model.skip) { 69118 continue; 69119 } 69120 69121 if (helpers$1.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) { 69122 pointCurrent.mK = pointAfter.mK = 0; 69123 continue; 69124 } 69125 69126 alphaK = pointCurrent.mK / pointCurrent.deltaK; 69127 betaK = pointAfter.mK / pointCurrent.deltaK; 69128 squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); 69129 if (squaredMagnitude <= 9) { 69130 continue; 69131 } 69132 69133 tauK = 3 / Math.sqrt(squaredMagnitude); 69134 pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK; 69135 pointAfter.mK = betaK * tauK * pointCurrent.deltaK; 69136 } 69137 69138 // Compute control points 69139 var deltaX; 69140 for (i = 0; i < pointsLen; ++i) { 69141 pointCurrent = pointsWithTangents[i]; 69142 if (pointCurrent.model.skip) { 69143 continue; 69144 } 69145 69146 pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; 69147 pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; 69148 if (pointBefore && !pointBefore.model.skip) { 69149 deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3; 69150 pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX; 69151 pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK; 69152 } 69153 if (pointAfter && !pointAfter.model.skip) { 69154 deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3; 69155 pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX; 69156 pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK; 69157 } 69158 } 69159 }; 69160 helpers$1.nextItem = function(collection, index, loop) { 69161 if (loop) { 69162 return index >= collection.length - 1 ? collection[0] : collection[index + 1]; 69163 } 69164 return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1]; 69165 }; 69166 helpers$1.previousItem = function(collection, index, loop) { 69167 if (loop) { 69168 return index <= 0 ? collection[collection.length - 1] : collection[index - 1]; 69169 } 69170 return index <= 0 ? collection[0] : collection[index - 1]; 69171 }; 69172 // Implementation of the nice number algorithm used in determining where axis labels will go 69173 helpers$1.niceNum = function(range, round) { 69174 var exponent = Math.floor(helpers$1.log10(range)); 69175 var fraction = range / Math.pow(10, exponent); 69176 var niceFraction; 69177 69178 if (round) { 69179 if (fraction < 1.5) { 69180 niceFraction = 1; 69181 } else if (fraction < 3) { 69182 niceFraction = 2; 69183 } else if (fraction < 7) { 69184 niceFraction = 5; 69185 } else { 69186 niceFraction = 10; 69187 } 69188 } else if (fraction <= 1.0) { 69189 niceFraction = 1; 69190 } else if (fraction <= 2) { 69191 niceFraction = 2; 69192 } else if (fraction <= 5) { 69193 niceFraction = 5; 69194 } else { 69195 niceFraction = 10; 69196 } 69197 69198 return niceFraction * Math.pow(10, exponent); 69199 }; 69200 // Request animation polyfill - https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ 69201 helpers$1.requestAnimFrame = (function() { 69202 if (typeof window === 'undefined') { 69203 return function(callback) { 69204 callback(); 69205 }; 69206 } 69207 return window.requestAnimationFrame || 69208 window.webkitRequestAnimationFrame || 69209 window.mozRequestAnimationFrame || 69210 window.oRequestAnimationFrame || 69211 window.msRequestAnimationFrame || 69212 function(callback) { 69213 return window.setTimeout(callback, 1000 / 60); 69214 }; 69215 }()); 69216 // -- DOM methods 69217 helpers$1.getRelativePosition = function(evt, chart) { 69218 var mouseX, mouseY; 69219 var e = evt.originalEvent || evt; 69220 var canvas = evt.target || evt.srcElement; 69221 var boundingRect = canvas.getBoundingClientRect(); 69222 69223 var touches = e.touches; 69224 if (touches && touches.length > 0) { 69225 mouseX = touches[0].clientX; 69226 mouseY = touches[0].clientY; 69227 69228 } else { 69229 mouseX = e.clientX; 69230 mouseY = e.clientY; 69231 } 69232 69233 // Scale mouse coordinates into canvas coordinates 69234 // by following the pattern laid out by 'jerryj' in the comments of 69235 // https://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ 69236 var paddingLeft = parseFloat(helpers$1.getStyle(canvas, 'padding-left')); 69237 var paddingTop = parseFloat(helpers$1.getStyle(canvas, 'padding-top')); 69238 var paddingRight = parseFloat(helpers$1.getStyle(canvas, 'padding-right')); 69239 var paddingBottom = parseFloat(helpers$1.getStyle(canvas, 'padding-bottom')); 69240 var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight; 69241 var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom; 69242 69243 // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However 69244 // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here 69245 mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio); 69246 mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio); 69247 69248 return { 69249 x: mouseX, 69250 y: mouseY 69251 }; 69252 69253 }; 69254 69255 // Private helper function to convert max-width/max-height values that may be percentages into a number 69256 function parseMaxStyle(styleValue, node, parentProperty) { 69257 var valueInPixels; 69258 if (typeof styleValue === 'string') { 69259 valueInPixels = parseInt(styleValue, 10); 69260 69261 if (styleValue.indexOf('%') !== -1) { 69262 // percentage * size in dimension 69263 valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; 69264 } 69265 } else { 69266 valueInPixels = styleValue; 69267 } 69268 69269 return valueInPixels; 69270 } 69271 69272 /** 69273 * Returns if the given value contains an effective constraint. 69274 * @private 69275 */ 69276 function isConstrainedValue(value) { 69277 return value !== undefined && value !== null && value !== 'none'; 69278 } 69279 69280 /** 69281 * Returns the max width or height of the given DOM node in a cross-browser compatible fashion 69282 * @param {HTMLElement} domNode - the node to check the constraint on 69283 * @param {string} maxStyle - the style that defines the maximum for the direction we are using ('max-width' / 'max-height') 69284 * @param {string} percentageProperty - property of parent to use when calculating width as a percentage 69285 * @see {@link https://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser} 69286 */ 69287 function getConstraintDimension(domNode, maxStyle, percentageProperty) { 69288 var view = document.defaultView; 69289 var parentNode = helpers$1._getParentNode(domNode); 69290 var constrainedNode = view.getComputedStyle(domNode)[maxStyle]; 69291 var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle]; 69292 var hasCNode = isConstrainedValue(constrainedNode); 69293 var hasCContainer = isConstrainedValue(constrainedContainer); 69294 var infinity = Number.POSITIVE_INFINITY; 69295 69296 if (hasCNode || hasCContainer) { 69297 return Math.min( 69298 hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity, 69299 hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity); 69300 } 69301 69302 return 'none'; 69303 } 69304 // returns Number or undefined if no constraint 69305 helpers$1.getConstraintWidth = function(domNode) { 69306 return getConstraintDimension(domNode, 'max-width', 'clientWidth'); 69307 }; 69308 // returns Number or undefined if no constraint 69309 helpers$1.getConstraintHeight = function(domNode) { 69310 return getConstraintDimension(domNode, 'max-height', 'clientHeight'); 69311 }; 69312 /** 69313 * @private 69314 */ 69315 helpers$1._calculatePadding = function(container, padding, parentDimension) { 69316 padding = helpers$1.getStyle(container, padding); 69317 69318 return padding.indexOf('%') > -1 ? parentDimension * parseInt(padding, 10) / 100 : parseInt(padding, 10); 69319 }; 69320 /** 69321 * @private 69322 */ 69323 helpers$1._getParentNode = function(domNode) { 69324 var parent = domNode.parentNode; 69325 if (parent && parent.toString() === '[object ShadowRoot]') { 69326 parent = parent.host; 69327 } 69328 return parent; 69329 }; 69330 helpers$1.getMaximumWidth = function(domNode) { 69331 var container = helpers$1._getParentNode(domNode); 69332 if (!container) { 69333 return domNode.clientWidth; 69334 } 69335 69336 var clientWidth = container.clientWidth; 69337 var paddingLeft = helpers$1._calculatePadding(container, 'padding-left', clientWidth); 69338 var paddingRight = helpers$1._calculatePadding(container, 'padding-right', clientWidth); 69339 69340 var w = clientWidth - paddingLeft - paddingRight; 69341 var cw = helpers$1.getConstraintWidth(domNode); 69342 return isNaN(cw) ? w : Math.min(w, cw); 69343 }; 69344 helpers$1.getMaximumHeight = function(domNode) { 69345 var container = helpers$1._getParentNode(domNode); 69346 if (!container) { 69347 return domNode.clientHeight; 69348 } 69349 69350 var clientHeight = container.clientHeight; 69351 var paddingTop = helpers$1._calculatePadding(container, 'padding-top', clientHeight); 69352 var paddingBottom = helpers$1._calculatePadding(container, 'padding-bottom', clientHeight); 69353 69354 var h = clientHeight - paddingTop - paddingBottom; 69355 var ch = helpers$1.getConstraintHeight(domNode); 69356 return isNaN(ch) ? h : Math.min(h, ch); 69357 }; 69358 helpers$1.getStyle = function(el, property) { 69359 return el.currentStyle ? 69360 el.currentStyle[property] : 69361 document.defaultView.getComputedStyle(el, null).getPropertyValue(property); 69362 }; 69363 helpers$1.retinaScale = function(chart, forceRatio) { 69364 var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1; 69365 if (pixelRatio === 1) { 69366 return; 69367 } 69368 69369 var canvas = chart.canvas; 69370 var height = chart.height; 69371 var width = chart.width; 69372 69373 canvas.height = height * pixelRatio; 69374 canvas.width = width * pixelRatio; 69375 chart.ctx.scale(pixelRatio, pixelRatio); 69376 69377 // If no style has been set on the canvas, the render size is used as display size, 69378 // making the chart visually bigger, so let's enforce it to the "correct" values. 69379 // See https://github.com/chartjs/Chart.js/issues/3575 69380 if (!canvas.style.height && !canvas.style.width) { 69381 canvas.style.height = height + 'px'; 69382 canvas.style.width = width + 'px'; 69383 } 69384 }; 69385 // -- Canvas methods 69386 helpers$1.fontString = function(pixelSize, fontStyle, fontFamily) { 69387 return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; 69388 }; 69389 helpers$1.longestText = function(ctx, font, arrayOfThings, cache) { 69390 cache = cache || {}; 69391 var data = cache.data = cache.data || {}; 69392 var gc = cache.garbageCollect = cache.garbageCollect || []; 69393 69394 if (cache.font !== font) { 69395 data = cache.data = {}; 69396 gc = cache.garbageCollect = []; 69397 cache.font = font; 69398 } 69399 69400 ctx.font = font; 69401 var longest = 0; 69402 helpers$1.each(arrayOfThings, function(thing) { 69403 // Undefined strings and arrays should not be measured 69404 if (thing !== undefined && thing !== null && helpers$1.isArray(thing) !== true) { 69405 longest = helpers$1.measureText(ctx, data, gc, longest, thing); 69406 } else if (helpers$1.isArray(thing)) { 69407 // if it is an array lets measure each element 69408 // to do maybe simplify this function a bit so we can do this more recursively? 69409 helpers$1.each(thing, function(nestedThing) { 69410 // Undefined strings and arrays should not be measured 69411 if (nestedThing !== undefined && nestedThing !== null && !helpers$1.isArray(nestedThing)) { 69412 longest = helpers$1.measureText(ctx, data, gc, longest, nestedThing); 69413 } 69414 }); 69415 } 69416 }); 69417 69418 var gcLen = gc.length / 2; 69419 if (gcLen > arrayOfThings.length) { 69420 for (var i = 0; i < gcLen; i++) { 69421 delete data[gc[i]]; 69422 } 69423 gc.splice(0, gcLen); 69424 } 69425 return longest; 69426 }; 69427 helpers$1.measureText = function(ctx, data, gc, longest, string) { 69428 var textWidth = data[string]; 69429 if (!textWidth) { 69430 textWidth = data[string] = ctx.measureText(string).width; 69431 gc.push(string); 69432 } 69433 if (textWidth > longest) { 69434 longest = textWidth; 69435 } 69436 return longest; 69437 }; 69438 helpers$1.numberOfLabelLines = function(arrayOfThings) { 69439 var numberOfLines = 1; 69440 helpers$1.each(arrayOfThings, function(thing) { 69441 if (helpers$1.isArray(thing)) { 69442 if (thing.length > numberOfLines) { 69443 numberOfLines = thing.length; 69444 } 69445 } 69446 }); 69447 return numberOfLines; 69448 }; 69449 69450 helpers$1.color = !chartjsColor ? 69451 function(value) { 69452 console.error('Color.js not found!'); 69453 return value; 69454 } : 69455 function(value) { 69456 /* global CanvasGradient */ 69457 if (value instanceof CanvasGradient) { 69458 value = core_defaults.global.defaultColor; 69459 } 69460 69461 return chartjsColor(value); 69462 }; 69463 69464 helpers$1.getHoverColor = function(colorValue) { 69465 /* global CanvasPattern */ 69466 return (colorValue instanceof CanvasPattern || colorValue instanceof CanvasGradient) ? 69467 colorValue : 69468 helpers$1.color(colorValue).saturate(0.5).darken(0.1).rgbString(); 69469 }; 69470}; 69471 69472function abstract() { 69473 throw new Error( 69474 'This method is not implemented: either no adapter can ' + 69475 'be found or an incomplete integration was provided.' 69476 ); 69477} 69478 69479/** 69480 * Date adapter (current used by the time scale) 69481 * @namespace Chart._adapters._date 69482 * @memberof Chart._adapters 69483 * @private 69484 */ 69485 69486/** 69487 * Currently supported unit string values. 69488 * @typedef {('millisecond'|'second'|'minute'|'hour'|'day'|'week'|'month'|'quarter'|'year')} 69489 * @memberof Chart._adapters._date 69490 * @name Unit 69491 */ 69492 69493/** 69494 * @class 69495 */ 69496function DateAdapter(options) { 69497 this.options = options || {}; 69498} 69499 69500helpers$1.extend(DateAdapter.prototype, /** @lends DateAdapter */ { 69501 /** 69502 * Returns a map of time formats for the supported formatting units defined 69503 * in Unit as well as 'datetime' representing a detailed date/time string. 69504 * @returns {{string: string}} 69505 */ 69506 formats: abstract, 69507 69508 /** 69509 * Parses the given `value` and return the associated timestamp. 69510 * @param {any} value - the value to parse (usually comes from the data) 69511 * @param {string} [format] - the expected data format 69512 * @returns {(number|null)} 69513 * @function 69514 */ 69515 parse: abstract, 69516 69517 /** 69518 * Returns the formatted date in the specified `format` for a given `timestamp`. 69519 * @param {number} timestamp - the timestamp to format 69520 * @param {string} format - the date/time token 69521 * @return {string} 69522 * @function 69523 */ 69524 format: abstract, 69525 69526 /** 69527 * Adds the specified `amount` of `unit` to the given `timestamp`. 69528 * @param {number} timestamp - the input timestamp 69529 * @param {number} amount - the amount to add 69530 * @param {Unit} unit - the unit as string 69531 * @return {number} 69532 * @function 69533 */ 69534 add: abstract, 69535 69536 /** 69537 * Returns the number of `unit` between the given timestamps. 69538 * @param {number} max - the input timestamp (reference) 69539 * @param {number} min - the timestamp to substract 69540 * @param {Unit} unit - the unit as string 69541 * @return {number} 69542 * @function 69543 */ 69544 diff: abstract, 69545 69546 /** 69547 * Returns start of `unit` for the given `timestamp`. 69548 * @param {number} timestamp - the input timestamp 69549 * @param {Unit} unit - the unit as string 69550 * @param {number} [weekday] - the ISO day of the week with 1 being Monday 69551 * and 7 being Sunday (only needed if param *unit* is `isoWeek`). 69552 * @function 69553 */ 69554 startOf: abstract, 69555 69556 /** 69557 * Returns end of `unit` for the given `timestamp`. 69558 * @param {number} timestamp - the input timestamp 69559 * @param {Unit} unit - the unit as string 69560 * @function 69561 */ 69562 endOf: abstract, 69563 69564 // DEPRECATIONS 69565 69566 /** 69567 * Provided for backward compatibility for scale.getValueForPixel(), 69568 * this method should be overridden only by the moment adapter. 69569 * @deprecated since version 2.8.0 69570 * @todo remove at version 3 69571 * @private 69572 */ 69573 _create: function(value) { 69574 return value; 69575 } 69576}); 69577 69578DateAdapter.override = function(members) { 69579 helpers$1.extend(DateAdapter.prototype, members); 69580}; 69581 69582var _date = DateAdapter; 69583 69584var core_adapters = { 69585 _date: _date 69586}; 69587 69588/** 69589 * Namespace to hold static tick generation functions 69590 * @namespace Chart.Ticks 69591 */ 69592var core_ticks = { 69593 /** 69594 * Namespace to hold formatters for different types of ticks 69595 * @namespace Chart.Ticks.formatters 69596 */ 69597 formatters: { 69598 /** 69599 * Formatter for value labels 69600 * @method Chart.Ticks.formatters.values 69601 * @param value the value to display 69602 * @return {string|string[]} the label to display 69603 */ 69604 values: function(value) { 69605 return helpers$1.isArray(value) ? value : '' + value; 69606 }, 69607 69608 /** 69609 * Formatter for linear numeric ticks 69610 * @method Chart.Ticks.formatters.linear 69611 * @param tickValue {number} the value to be formatted 69612 * @param index {number} the position of the tickValue parameter in the ticks array 69613 * @param ticks {number[]} the list of ticks being converted 69614 * @return {string} string representation of the tickValue parameter 69615 */ 69616 linear: function(tickValue, index, ticks) { 69617 // If we have lots of ticks, don't use the ones 69618 var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; 69619 69620 // If we have a number like 2.5 as the delta, figure out how many decimal places we need 69621 if (Math.abs(delta) > 1) { 69622 if (tickValue !== Math.floor(tickValue)) { 69623 // not an integer 69624 delta = tickValue - Math.floor(tickValue); 69625 } 69626 } 69627 69628 var logDelta = helpers$1.log10(Math.abs(delta)); 69629 var tickString = ''; 69630 69631 if (tickValue !== 0) { 69632 var maxTick = Math.max(Math.abs(ticks[0]), Math.abs(ticks[ticks.length - 1])); 69633 if (maxTick < 1e-4) { // all ticks are small numbers; use scientific notation 69634 var logTick = helpers$1.log10(Math.abs(tickValue)); 69635 tickString = tickValue.toExponential(Math.floor(logTick) - Math.floor(logDelta)); 69636 } else { 69637 var numDecimal = -1 * Math.floor(logDelta); 69638 numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places 69639 tickString = tickValue.toFixed(numDecimal); 69640 } 69641 } else { 69642 tickString = '0'; // never show decimal places for 0 69643 } 69644 69645 return tickString; 69646 }, 69647 69648 logarithmic: function(tickValue, index, ticks) { 69649 var remain = tickValue / (Math.pow(10, Math.floor(helpers$1.log10(tickValue)))); 69650 69651 if (tickValue === 0) { 69652 return '0'; 69653 } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { 69654 return tickValue.toExponential(); 69655 } 69656 return ''; 69657 } 69658 } 69659}; 69660 69661var valueOrDefault$9 = helpers$1.valueOrDefault; 69662var valueAtIndexOrDefault = helpers$1.valueAtIndexOrDefault; 69663 69664core_defaults._set('scale', { 69665 display: true, 69666 position: 'left', 69667 offset: false, 69668 69669 // grid line settings 69670 gridLines: { 69671 display: true, 69672 color: 'rgba(0, 0, 0, 0.1)', 69673 lineWidth: 1, 69674 drawBorder: true, 69675 drawOnChartArea: true, 69676 drawTicks: true, 69677 tickMarkLength: 10,
69678 zeroLineWidth: 1, 69679 zeroLineColor: 'rgba(0,0,0,0.25)', 69680 zeroLineBorderDash: [], 69681 zeroLineBorderDashOffset: 0.0, 69682 offsetGridLines: false, 69683 borderDash: [], 69684 borderDashOffset: 0.0 69685 }, 69686 69687 // scale label 69688 scaleLabel: { 69689 // display property 69690 display: false, 69691 69692 // actual label 69693 labelString: '', 69694 69695 // top/bottom padding 69696 padding: { 69697 top: 4, 69698 bottom: 4 69699 } 69700 }, 69701 69702 // label settings 69703 ticks: { 69704 beginAtZero: false, 69705 minRotation: 0, 69706 maxRotation: 50, 69707 mirror: false, 69708 padding: 0, 69709 reverse: false, 69710 display: true, 69711 autoSkip: true, 69712 autoSkipPadding: 0, 69713 labelOffset: 0, 69714 // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. 69715 callback: core_ticks.formatters.values, 69716 minor: {}, 69717 major: {} 69718 } 69719}); 69720 69721function labelsFromTicks(ticks) { 69722 var labels = []; 69723 var i, ilen; 69724 69725 for (i = 0, ilen = ticks.length; i < ilen; ++i) { 69726 labels.push(ticks[i].label); 69727 } 69728 69729 return labels; 69730} 69731 69732function getPixelForGridLine(scale, index, offsetGridLines) { 69733 var lineValue = scale.getPixelForTick(index); 69734 69735 if (offsetGridLines) { 69736 if (scale.getTicks().length === 1) { 69737 lineValue -= scale.isHorizontal() ? 69738 Math.max(lineValue - scale.left, scale.right - lineValue) : 69739 Math.max(lineValue - scale.top, scale.bottom - lineValue); 69740 } else if (index === 0) { 69741 lineValue -= (scale.getPixelForTick(1) - lineValue) / 2; 69742 } else { 69743 lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2; 69744 } 69745 } 69746 return lineValue; 69747} 69748 69749function computeTextSize(context, tick, font) { 69750 return helpers$1.isArray(tick) ? 69751 helpers$1.longestText(context, font, tick) : 69752 context.measureText(tick).width; 69753} 69754 69755var core_scale = core_element.extend({ 69756 /** 69757 * Get the padding needed for the scale 69758 * @method getPadding 69759 * @private 69760 * @returns {Padding} the necessary padding 69761 */ 69762 getPadding: function() { 69763 var me = this; 69764 return { 69765 left: me.paddingLeft || 0, 69766 top: me.paddingTop || 0, 69767 right: me.paddingRight || 0, 69768 bottom: me.paddingBottom || 0 69769 }; 69770 }, 69771 69772 /** 69773 * Returns the scale tick objects ({label, major}) 69774 * @since 2.7 69775 */ 69776 getTicks: function() { 69777 return this._ticks; 69778 }, 69779 69780 // These methods are ordered by lifecyle. Utilities then follow. 69781 // Any function defined here is inherited by all scale types. 69782 // Any function can be extended by the scale type 69783 69784 mergeTicksOptions: function() { 69785 var ticks = this.options.ticks; 69786 if (ticks.minor === false) { 69787 ticks.minor = { 69788 display: false 69789 }; 69790 } 69791 if (ticks.major === false) { 69792 ticks.major = { 69793 display: false 69794 }; 69795 } 69796 for (var key in ticks) { 69797 if (key !== 'major' && key !== 'minor') { 69798 if (typeof ticks.minor[key] === 'undefined') { 69799 ticks.minor[key] = ticks[key]; 69800 } 69801 if (typeof ticks.major[key] === 'undefined') { 69802 ticks.major[key] = ticks[key]; 69803 } 69804 } 69805 } 69806 }, 69807 beforeUpdate: function() { 69808 helpers$1.callback(this.options.beforeUpdate, [this]); 69809 }, 69810 69811 update: function(maxWidth, maxHeight, margins) { 69812 var me = this; 69813 var i, ilen, labels, label, ticks, tick; 69814 69815 // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) 69816 me.beforeUpdate(); 69817 69818 // Absorb the master measurements 69819 me.maxWidth = maxWidth; 69820 me.maxHeight = maxHeight; 69821 me.margins = helpers$1.extend({ 69822 left: 0, 69823 right: 0, 69824 top: 0, 69825 bottom: 0 69826 }, margins); 69827 69828 me._maxLabelLines = 0; 69829 me.longestLabelWidth = 0; 69830 me.longestTextCache = me.longestTextCache || {}; 69831 69832 // Dimensions 69833 me.beforeSetDimensions(); 69834 me.setDimensions(); 69835 me.afterSetDimensions(); 69836 69837 // Data min/max 69838 me.beforeDataLimits(); 69839 me.determineDataLimits(); 69840 me.afterDataLimits(); 69841 69842 // Ticks - `this.ticks` is now DEPRECATED! 69843 // Internal ticks are now stored as objects in the PRIVATE `this._ticks` member 69844 // and must not be accessed directly from outside this class. `this.ticks` being 69845 // around for long time and not marked as private, we can't change its structure 69846 // without unexpected breaking changes. If you need to access the scale ticks, 69847 // use scale.getTicks() instead. 69848 69849 me.beforeBuildTicks(); 69850 69851 // New implementations should return an array of objects but for BACKWARD COMPAT, 69852 // we still support no return (`this.ticks` internally set by calling this method). 69853 ticks = me.buildTicks() || []; 69854 69855 // Allow modification of ticks in callback. 69856 ticks = me.afterBuildTicks(ticks) || ticks; 69857 69858 me.beforeTickToLabelConversion(); 69859 69860 // New implementations should return the formatted tick labels but for BACKWARD 69861 // COMPAT, we still support no return (`this.ticks` internally changed by calling 69862 // this method and supposed to contain only string values). 69863 labels = me.convertTicksToLabels(ticks) || me.ticks; 69864 69865 me.afterTickToLabelConversion(); 69866 69867 me.ticks = labels; // BACKWARD COMPATIBILITY 69868 69869 // IMPORTANT: from this point, we consider that `this.ticks` will NEVER change! 69870 69871 // BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`) 69872 for (i = 0, ilen = labels.length; i < ilen; ++i) { 69873 label = labels[i]; 69874 tick = ticks[i]; 69875 if (!tick) { 69876 ticks.push(tick = { 69877 label: label, 69878 major: false 69879 }); 69880 } else { 69881 tick.label = label; 69882 } 69883 } 69884 69885 me._ticks = ticks; 69886 69887 // Tick Rotation 69888 me.beforeCalculateTickRotation(); 69889 me.calculateTickRotation(); 69890 me.afterCalculateTickRotation(); 69891 // Fit 69892 me.beforeFit(); 69893 me.fit(); 69894 me.afterFit(); 69895 // 69896 me.afterUpdate(); 69897 69898 return me.minSize; 69899 69900 }, 69901 afterUpdate: function() { 69902 helpers$1.callback(this.options.afterUpdate, [this]); 69903 }, 69904 69905 // 69906 69907 beforeSetDimensions: function() { 69908 helpers$1.callback(this.options.beforeSetDimensions, [this]); 69909 }, 69910 setDimensions: function() { 69911 var me = this; 69912 // Set the unconstrained dimension before label rotation 69913 if (me.isHorizontal()) { 69914 // Reset position before calculating rotation 69915 me.width = me.maxWidth; 69916 me.left = 0; 69917 me.right = me.width; 69918 } else { 69919 me.height = me.maxHeight; 69920 69921 // Reset position before calculating rotation 69922 me.top = 0; 69923 me.bottom = me.height; 69924 } 69925 69926 // Reset padding 69927 me.paddingLeft = 0; 69928 me.paddingTop = 0; 69929 me.paddingRight = 0; 69930 me.paddingBottom = 0; 69931 }, 69932 afterSetDimensions: function() { 69933 helpers$1.callback(this.options.afterSetDimensions, [this]); 69934 }, 69935 69936 // Data limits 69937 beforeDataLimits: function() { 69938 helpers$1.callback(this.options.beforeDataLimits, [this]); 69939 }, 69940 determineDataLimits: helpers$1.noop, 69941 afterDataLimits: function() { 69942 helpers$1.callback(this.options.afterDataLimits, [this]); 69943 }, 69944 69945 // 69946 beforeBuildTicks: function() { 69947 helpers$1.callback(this.options.beforeBuildTicks, [this]); 69948 }, 69949 buildTicks: helpers$1.noop, 69950 afterBuildTicks: function(ticks) { 69951 var me = this; 69952 // ticks is empty for old axis implementations here 69953 if (helpers$1.isArray(ticks) && ticks.length) { 69954 return helpers$1.callback(me.options.afterBuildTicks, [me, ticks]); 69955 }
69956 // Support old implementations (that modified `this.ticks` directly in buildTicks) 69957 me.ticks = helpers$1.callback(me.options.afterBuildTicks, [me, me.ticks]) || me.ticks; 69958 return ticks; 69959 }, 69960 69961 beforeTickToLabelConversion: function() { 69962 helpers$1.callback(this.options.beforeTickToLabelConversion, [this]); 69963 }, 69964 convertTicksToLabels: function() { 69965 var me = this; 69966 // Convert ticks to strings 69967 var tickOpts = me.options.ticks; 69968 me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this); 69969 }, 69970 afterTickToLabelConversion: function() { 69971 helpers$1.callback(this.options.afterTickToLabelConversion, [this]); 69972 }, 69973 69974 // 69975 69976 beforeCalculateTickRotation: function() { 69977 helpers$1.callback(this.options.beforeCalculateTickRotation, [this]); 69978 }, 69979 calculateTickRotation: function() { 69980 var me = this; 69981 var context = me.ctx; 69982 var tickOpts = me.options.ticks; 69983 var labels = labelsFromTicks(me._ticks); 69984 69985 // Get the width of each grid by calculating the difference 69986 // between x offsets between 0 and 1. 69987 var tickFont = helpers$1.options._parseFont(tickOpts); 69988 context.font = tickFont.string; 69989 69990 var labelRotation = tickOpts.minRotation || 0; 69991 69992 if (labels.length && me.options.display && me.isHorizontal()) { 69993 var originalLabelWidth = helpers$1.longestText(context, tickFont.string, labels, me.longestTextCache); 69994 var labelWidth = originalLabelWidth; 69995 var cosRotation, sinRotation; 69996 69997 // Allow 3 pixels x2 padding either side for label readability 69998 var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6; 69999 70000 // Max label rotation can be set or default to 90 - also act as a loop counter 70001 while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) { 70002 var angleRadians = helpers$1.toRadians(labelRotation); 70003 cosRotation = Math.cos(angleRadians); 70004 sinRotation = Math.sin(angleRadians); 70005 70006 if (sinRotation * originalLabelWidth > me.maxHeight) { 70007 // go back one step 70008 labelRotation--; 70009 break; 70010 } 70011 70012 labelRotation++; 70013 labelWidth = cosRotation * originalLabelWidth; 70014 } 70015 } 70016 70017 me.labelRotation = labelRotation; 70018 }, 70019 afterCalculateTickRotation: function() { 70020 helpers$1.callback(this.options.afterCalculateTickRotation, [this]); 70021 }, 70022 70023 // 70024 70025 beforeFit: function() { 70026 helpers$1.callback(this.options.beforeFit, [this]); 70027 }, 70028 fit: function() { 70029 var me = this; 70030 // Reset 70031 var minSize = me.minSize = { 70032 width: 0, 70033 height: 0 70034 }; 70035 70036 var labels = labelsFromTicks(me._ticks); 70037 70038 var opts = me.options; 70039 var tickOpts = opts.ticks; 70040 var scaleLabelOpts = opts.scaleLabel; 70041 var gridLineOpts = opts.gridLines; 70042 var display = me._isVisible(); 70043 var position = opts.position; 70044 var isHorizontal = me.isHorizontal(); 70045 70046 var parseFont = helpers$1.options._parseFont; 70047 var tickFont = parseFont(tickOpts); 70048 var tickMarkLength = opts.gridLines.tickMarkLength; 70049 70050 // Width 70051 if (isHorizontal) { 70052 // subtract the margins to line up with the chartArea if we are a full width scale 70053 minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth; 70054 } else { 70055 minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0; 70056 } 70057 70058 // height 70059 if (isHorizontal) { 70060 minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0; 70061 } else { 70062 minSize.height = me.maxHeight; // fill all the height 70063 } 70064 70065 // Are we showing a title for the scale? 70066 if (scaleLabelOpts.display && display) { 70067 var scaleLabelFont = parseFont(scaleLabelOpts); 70068 var scaleLabelPadding = helpers$1.options.toPadding(scaleLabelOpts.padding); 70069 var deltaHeight = scaleLabelFont.lineHeight + scaleLabelPadding.height; 70070 70071 if (isHorizontal) { 70072 minSize.height += deltaHeight; 70073 } else { 70074 minSize.width += deltaHeight; 70075 } 70076 } 70077 70078 // Don't bother fitting the ticks if we are not showing the labels 70079 if (tickOpts.display && display) { 70080 var largestTextWidth = helpers$1.longestText(me.ctx, tickFont.string, labels, me.longestTextCache); 70081 var tallestLabelHeightInLines = helpers$1.numberOfLabelLines(labels); 70082 var lineSpace = tickFont.size * 0.5; 70083 var tickPadding = me.options.ticks.padding; 70084 70085 // Store max number of lines and widest label for _autoSkip 70086 me._maxLabelLines = tallestLabelHeightInLines; 70087 me.longestLabelWidth = largestTextWidth; 70088 70089 if (isHorizontal) { 70090 var angleRadians = helpers$1.toRadians(me.labelRotation); 70091 var cosRotation = Math.cos(angleRadians); 70092 var sinRotation = Math.sin(angleRadians); 70093 70094 // TODO - improve this calculation 70095 var labelHeight = (sinRotation * largestTextWidth) 70096 + (tickFont.lineHeight * tallestLabelHeightInLines) 70097 + lineSpace; // padding 70098 70099 minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding); 70100 70101 me.ctx.font = tickFont.string; 70102 var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.string); 70103 var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.string); 70104 var offsetLeft = me.getPixelForTick(0) - me.left; 70105 var offsetRight = me.right - me.getPixelForTick(labels.length - 1); 70106 var paddingLeft, paddingRight; 70107 70108 // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned 70109 // which means that the right padding is dominated by the font height 70110 if (me.labelRotation !== 0) { 70111 paddingLeft = position === 'bottom' ? (cosRotation * firstLabelWidth) : (cosRotation * lineSpace); 70112 paddingRight = position === 'bottom' ? (cosRotation * lineSpace) : (cosRotation * lastLabelWidth); 70113 } else {
70114 paddingLeft = firstLabelWidth / 2; 70115 paddingRight = lastLabelWidth / 2; 70116 } 70117 me.paddingLeft = Math.max(paddingLeft - offsetLeft, 0) + 3; // add 3 px to move away from canvas edges 70118 me.paddingRight = Math.max(paddingRight - offsetRight, 0) + 3; 70119 } else { 70120 // A vertical axis is more constrained by the width. Labels are the 70121 // dominant factor here, so get that length first and account for padding 70122 if (tickOpts.mirror) { 70123 largestTextWidth = 0; 70124 } else { 70125 // use lineSpace for consistency with horizontal axis 70126 // tickPadding is not implemented for horizontal 70127 largestTextWidth += tickPadding + lineSpace; 70128 } 70129 70130 minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth); 70131 70132 me.paddingTop = tickFont.size / 2; 70133 me.paddingBottom = tickFont.size / 2; 70134 } 70135 } 70136 70137 me.handleMargins(); 70138 70139 me.width = minSize.width; 70140 me.height = minSize.height; 70141 }, 70142 70143 /** 70144 * Handle margins and padding interactions 70145 * @private 70146 */ 70147 handleMargins: function() { 70148 var me = this; 70149 if (me.margins) { 70150 me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0); 70151 me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0); 70152 me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0); 70153 me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0); 70154 } 70155 }, 70156 70157 afterFit: function() { 70158 helpers$1.callback(this.options.afterFit, [this]); 70159 }, 70160 70161 // Shared Methods 70162 isHorizontal: function() { 70163 return this.options.position === 'top' || this.options.position === 'bottom'; 70164 }, 70165 isFullWidth: function() { 70166 return (this.options.fullWidth); 70167 }, 70168 70169 // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not 70170 getRightValue: function(rawValue) { 70171 // Null and undefined values first 70172 if (helpers$1.isNullOrUndef(rawValue)) { 70173 return NaN; 70174 } 70175 // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values 70176 if ((typeof rawValue === 'number' || rawValue instanceof Number) && !isFinite(rawValue)) { 70177 return NaN; 70178 } 70179 // If it is in fact an object, dive in one more level 70180 if (rawValue) { 70181 if (this.isHorizontal()) { 70182 if (rawValue.x !== undefined) { 70183 return this.getRightValue(rawValue.x); 70184 } 70185 } else if (rawValue.y !== undefined) { 70186 return this.getRightValue(rawValue.y); 70187 } 70188 } 70189 70190 // Value is good, return it 70191 return rawValue; 70192 }, 70193 70194 /** 70195 * Used to get the value to display in the tooltip for the data at the given index 70196 * @param index 70197 * @param datasetIndex 70198 */ 70199 getLabelForIndex: helpers$1.noop, 70200 70201 /** 70202 * Returns the location of the given data point. Value can either be an index or a numerical value 70203 * The coordinate (0, 0) is at the upper-left corner of the canvas 70204 * @param value 70205 * @param index 70206 * @param datasetIndex 70207 */ 70208 getPixelForValue: helpers$1.noop, 70209 70210 /** 70211 * Used to get the data value from a given pixel. This is the inverse of getPixelForValue 70212 * The coordinate (0, 0) is at the upper-left corner of the canvas 70213 * @param pixel 70214 */ 70215 getValueForPixel: helpers$1.noop, 70216 70217 /** 70218 * Returns the location of the tick at the given index 70219 * The coordinate (0, 0) is at the upper-left corner of the canvas 70220 */ 70221 getPixelForTick: function(index) { 70222 var me = this; 70223 var offset = me.options.offset; 70224 if (me.isHorizontal()) { 70225 var innerWidth = me.width - (me.paddingLeft + me.paddingRight); 70226 var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1); 70227 var pixel = (tickWidth * index) + me.paddingLeft; 70228 70229 if (offset) { 70230 pixel += tickWidth / 2; 70231 } 70232 70233 var finalVal = me.left + pixel; 70234 finalVal += me.isFullWidth() ? me.margins.left : 0; 70235 return finalVal; 70236 } 70237 var innerHeight = me.height - (me.paddingTop + me.paddingBottom); 70238 return me.top + (index * (innerHeight / (me._ticks.length - 1))); 70239 }, 70240 70241 /** 70242 * Utility for getting the pixel location of a percentage of scale 70243 * The coordinate (0, 0) is at the upper-left corner of the canvas 70244 */ 70245 getPixelForDecimal: function(decimal) { 70246 var me = this; 70247 if (me.isHorizontal()) { 70248 var innerWidth = me.width - (me.paddingLeft + me.paddingRight); 70249 var valueOffset = (innerWidth * decimal) + me.paddingLeft; 70250 70251 var finalVal = me.left + valueOffset; 70252 finalVal += me.isFullWidth() ? me.margins.left : 0; 70253 return finalVal; 70254 } 70255 return me.top + (decimal * me.height); 70256 }, 70257 70258 /** 70259 * Returns the pixel for the minimum chart value 70260 * The coordinate (0, 0) is at the upper-left corner of the canvas 70261 */ 70262 getBasePixel: function() { 70263 return this.getPixelForValue(this.getBaseValue()); 70264 }, 70265 70266 getBaseValue: function() { 70267 var me = this; 70268 var min = me.min; 70269 var max = me.max; 70270 70271 return me.beginAtZero ? 0 : 70272 min < 0 && max < 0 ? max : 70273 min > 0 && max > 0 ? min : 70274 0; 70275 }, 70276 70277 /** 70278 * Returns a subset of ticks to be plotted to avoid overlapping labels. 70279 * @private 70280 */ 70281 _autoSkip: function(ticks) { 70282 var me = this; 70283 var isHorizontal = me.isHorizontal(); 70284 var optionTicks = me.options.ticks.minor; 70285 var tickCount = ticks.length; 70286 var skipRatio = false;
70287 var maxTicks = optionTicks.maxTicksLimit; 70288 70289 // Total space needed to display all ticks. First and last ticks are 70290 // drawn as their center at end of axis, so tickCount-1 70291 var ticksLength = me._tickSize() * (tickCount - 1); 70292 70293 // Axis length 70294 var axisLength = isHorizontal 70295 ? me.width - (me.paddingLeft + me.paddingRight) 70296 : me.height - (me.paddingTop + me.PaddingBottom); 70297 70298 var result = []; 70299 var i, tick; 70300 70301 if (ticksLength > axisLength) { 70302 skipRatio = 1 + Math.floor(ticksLength / axisLength); 70303 } 70304 70305 // if they defined a max number of optionTicks, 70306 // increase skipRatio until that number is met 70307 if (tickCount > maxTicks) { 70308 skipRatio = Math.max(skipRatio, 1 + Math.floor(tickCount / maxTicks)); 70309 } 70310 70311 for (i = 0; i < tickCount; i++) { 70312 tick = ticks[i]; 70313 70314 if (skipRatio > 1 && i % skipRatio > 0) { 70315 // leave tick in place but make sure it's not displayed (#4635) 70316 delete tick.label; 70317 } 70318 result.push(tick); 70319 } 70320 return result; 70321 }, 70322 70323 /** 70324 * @private 70325 */ 70326 _tickSize: function() { 70327 var me = this; 70328 var isHorizontal = me.isHorizontal(); 70329 var optionTicks = me.options.ticks.minor; 70330 70331 // Calculate space needed by label in axis direction. 70332 var rot = helpers$1.toRadians(me.labelRotation); 70333 var cos = Math.abs(Math.cos(rot)); 70334 var sin = Math.abs(Math.sin(rot)); 70335 70336 var padding = optionTicks.autoSkipPadding || 0; 70337 var w = (me.longestLabelWidth + padding) || 0; 70338 70339 var tickFont = helpers$1.options._parseFont(optionTicks); 70340 var h = (me._maxLabelLines * tickFont.lineHeight + padding) || 0; 70341 70342 // Calculate space needed for 1 tick in axis direction. 70343 return isHorizontal 70344 ? h * cos > w * sin ? w / cos : h / sin 70345 : h * sin < w * cos ? h / cos : w / sin; 70346 }, 70347 70348 /** 70349 * @private 70350 */ 70351 _isVisible: function() { 70352 var me = this; 70353 var chart = me.chart; 70354 var display = me.options.display; 70355 var i, ilen, meta; 70356 70357 if (display !== 'auto') { 70358 return !!display; 70359 } 70360 70361 // When 'auto', the scale is visible if at least one associated dataset is visible. 70362 for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { 70363 if (chart.isDatasetVisible(i)) { 70364 meta = chart.getDatasetMeta(i); 70365 if (meta.xAxisID === me.id || meta.yAxisID === me.id) { 70366 return true; 70367 } 70368 } 70369 } 70370 70371 return false; 70372 }, 70373 70374 /** 70375 * Actually draw the scale on the canvas 70376 * @param {object} chartArea - the area of the chart to draw full grid lines on 70377 */ 70378 draw: function(chartArea) { 70379 var me = this; 70380 var options = me.options; 70381 70382 if (!me._isVisible()) { 70383 return; 70384 } 70385 70386 var chart = me.chart; 70387 var context = me.ctx; 70388 var globalDefaults = core_defaults.global; 70389 var defaultFontColor = globalDefaults.defaultFontColor; 70390 var optionTicks = options.ticks.minor; 70391 var optionMajorTicks = options.ticks.major || optionTicks; 70392 var gridLines = options.gridLines; 70393 var scaleLabel = options.scaleLabel; 70394 var position = options.position; 70395 70396 var isRotated = me.labelRotation !== 0; 70397 var isMirrored = optionTicks.mirror; 70398 var isHorizontal = me.isHorizontal(); 70399 70400 var parseFont = helpers$1.options._parseFont; 70401 var ticks = optionTicks.display && optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks(); 70402 var tickFontColor = valueOrDefault$9(optionTicks.fontColor, defaultFontColor); 70403 var tickFont = parseFont(optionTicks); 70404 var lineHeight = tickFont.lineHeight; 70405 var majorTickFontColor = valueOrDefault$9(optionMajorTicks.fontColor, defaultFontColor); 70406 var majorTickFont = parseFont(optionMajorTicks); 70407 var tickPadding = optionTicks.padding; 70408 var labelOffset = optionTicks.labelOffset; 70409 70410 var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0; 70411 70412 var scaleLabelFontColor = valueOrDefault$9(scaleLabel.fontColor, defaultFontColor); 70413 var scaleLabelFont = parseFont(scaleLabel); 70414 var scaleLabelPadding = helpers$1.options.toPadding(scaleLabel.padding); 70415 var labelRotationRadians = helpers$1.toRadians(me.labelRotation); 70416 70417 var itemsToDraw = []; 70418 70419 var axisWidth = gridLines.drawBorder ? valueAtIndexOrDefault(gridLines.lineWidth, 0, 0) : 0; 70420 var alignPixel = helpers$1._alignPixel; 70421 var borderValue, tickStart, tickEnd; 70422 70423 if (position === 'top') { 70424 borderValue = alignPixel(chart, me.bottom, axisWidth); 70425 tickStart = me.bottom - tl; 70426 tickEnd = borderValue - axisWidth / 2; 70427 } else if (position === 'bottom') { 70428 borderValue = alignPixel(chart, me.top, axisWidth); 70429 tickStart = borderValue + axisWidth / 2; 70430 tickEnd = me.top + tl; 70431 } else if (position === 'left') { 70432 borderValue = alignPixel(chart, me.right, axisWidth); 70433 tickStart = me.right - tl; 70434 tickEnd = borderValue - axisWidth / 2; 70435 } else { 70436 borderValue = alignPixel(chart, me.left, axisWidth); 70437 tickStart = borderValue + axisWidth / 2; 70438 tickEnd = me.left + tl; 70439 } 70440 70441 var epsilon = 0.0000001; // 0.0000001 is margin in pixels for Accumulated error. 70442 70443 helpers$1.each(ticks, function(tick, index) { 70444 // autoskipper skipped this tick (#4635) 70445 if (helpers$1.isNullOrUndef(tick.label)) { 70446 return; 70447 } 70448 70449 var label = tick.label; 70450 var lineWidth, lineColor, borderDash, borderDashOffset; 70451 if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) { 70452 // Draw the first index specially
70453 lineWidth = gridLines.zeroLineWidth; 70454 lineColor = gridLines.zeroLineColor; 70455 borderDash = gridLines.zeroLineBorderDash || []; 70456 borderDashOffset = gridLines.zeroLineBorderDashOffset || 0.0; 70457 } else { 70458 lineWidth = valueAtIndexOrDefault(gridLines.lineWidth, index); 70459 lineColor = valueAtIndexOrDefault(gridLines.color, index); 70460 borderDash = gridLines.borderDash || []; 70461 borderDashOffset = gridLines.borderDashOffset || 0.0; 70462 } 70463 70464 // Common properties 70465 var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY, textOffset, textAlign; 70466 var labelCount = helpers$1.isArray(label) ? label.length : 1; 70467 var lineValue = getPixelForGridLine(me, index, gridLines.offsetGridLines); 70468 70469 if (isHorizontal) { 70470 var labelYOffset = tl + tickPadding; 70471 70472 if (lineValue < me.left - epsilon) { 70473 lineColor = 'rgba(0,0,0,0)'; 70474 } 70475 70476 tx1 = tx2 = x1 = x2 = alignPixel(chart, lineValue, lineWidth); 70477 ty1 = tickStart; 70478 ty2 = tickEnd; 70479 labelX = me.getPixelForTick(index) + labelOffset; // x values for optionTicks (need to consider offsetLabel option) 70480 70481 if (position === 'top') { 70482 y1 = alignPixel(chart, chartArea.top, axisWidth) + axisWidth / 2; 70483 y2 = chartArea.bottom; 70484 textOffset = ((!isRotated ? 0.5 : 1) - labelCount) * lineHeight; 70485 textAlign = !isRotated ? 'center' : 'left'; 70486 labelY = me.bottom - labelYOffset; 70487 } else { 70488 y1 = chartArea.top; 70489 y2 = alignPixel(chart, chartArea.bottom, axisWidth) - axisWidth / 2; 70490 textOffset = (!isRotated ? 0.5 : 0) * lineHeight; 70491 textAlign = !isRotated ? 'center' : 'right'; 70492 labelY = me.top + labelYOffset; 70493 } 70494 } else { 70495 var labelXOffset = (isMirrored ? 0 : tl) + tickPadding; 70496 70497 if (lineValue < me.top - epsilon) { 70498 lineColor = 'rgba(0,0,0,0)'; 70499 } 70500 70501 tx1 = tickStart; 70502 tx2 = tickEnd; 70503 ty1 = ty2 = y1 = y2 = alignPixel(chart, lineValue, lineWidth); 70504 labelY = me.getPixelForTick(index) + labelOffset; 70505 textOffset = (1 - labelCount) * lineHeight / 2; 70506 70507 if (position === 'left') { 70508 x1 = alignPixel(chart, chartArea.left, axisWidth) + axisWidth / 2; 70509 x2 = chartArea.right; 70510 textAlign = isMirrored ? 'left' : 'right'; 70511 labelX = me.right - labelXOffset; 70512 } else { 70513 x1 = chartArea.left; 70514 x2 = alignPixel(chart, chartArea.right, axisWidth) - axisWidth / 2; 70515 textAlign = isMirrored ? 'right' : 'left'; 70516 labelX = me.left + labelXOffset; 70517 } 70518 } 70519 70520 itemsToDraw.push({ 70521 tx1: tx1, 70522 ty1: ty1, 70523 tx2: tx2, 70524 ty2: ty2, 70525 x1: x1, 70526 y1: y1, 70527 x2: x2, 70528 y2: y2, 70529 labelX: labelX, 70530 labelY: labelY, 70531 glWidth: lineWidth, 70532 glColor: lineColor, 70533 glBorderDash: borderDash, 70534 glBorderDashOffset: borderDashOffset, 70535 rotation: -1 * labelRotationRadians, 70536 label: label, 70537 major: tick.major, 70538 textOffset: textOffset, 70539 textAlign: textAlign 70540 }); 70541 }); 70542 70543 // Draw all of the tick labels, tick marks, and grid lines at the correct places 70544 helpers$1.each(itemsToDraw, function(itemToDraw) { 70545 var glWidth = itemToDraw.glWidth; 70546 var glColor = itemToDraw.glColor; 70547 70548 if (gridLines.display && glWidth && glColor) { 70549 context.save(); 70550 context.lineWidth = glWidth; 70551 context.strokeStyle = glColor; 70552 if (context.setLineDash) { 70553 context.setLineDash(itemToDraw.glBorderDash); 70554 context.lineDashOffset = itemToDraw.glBorderDashOffset; 70555 } 70556 70557 context.beginPath(); 70558 70559 if (gridLines.drawTicks) { 70560 context.moveTo(itemToDraw.tx1, itemToDraw.ty1); 70561 context.lineTo(itemToDraw.tx2, itemToDraw.ty2); 70562 } 70563 70564 if (gridLines.drawOnChartArea) { 70565 context.moveTo(itemToDraw.x1, itemToDraw.y1); 70566 context.lineTo(itemToDraw.x2, itemToDraw.y2); 70567 } 70568 70569 context.stroke(); 70570 context.restore(); 70571 } 70572 70573 if (optionTicks.display) { 70574 // Make sure we draw text in the correct color and font 70575 context.save(); 70576 context.translate(itemToDraw.labelX, itemToDraw.labelY); 70577 context.rotate(itemToDraw.rotation); 70578 context.font = itemToDraw.major ? majorTickFont.string : tickFont.string; 70579 context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor; 70580 context.textBaseline = 'middle'; 70581 context.textAlign = itemToDraw.textAlign; 70582 70583 var label = itemToDraw.label; 70584 var y = itemToDraw.textOffset; 70585 if (helpers$1.isArray(label)) { 70586 for (var i = 0; i < label.length; ++i) { 70587 // We just make sure the multiline element is a string here.. 70588 context.fillText('' + label[i], 0, y); 70589 y += lineHeight; 70590 } 70591 } else { 70592 context.fillText(label, 0, y); 70593 }
70594 context.restore(); 70595 } 70596 }); 70597 70598 if (scaleLabel.display) { 70599 // Draw the scale label 70600 var scaleLabelX; 70601 var scaleLabelY; 70602 var rotation = 0; 70603 var halfLineHeight = scaleLabelFont.lineHeight / 2; 70604 70605 if (isHorizontal) { 70606 scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width 70607 scaleLabelY = position === 'bottom' 70608 ? me.bottom - halfLineHeight - scaleLabelPadding.bottom 70609 : me.top + halfLineHeight + scaleLabelPadding.top; 70610 } else { 70611 var isLeft = position === 'left'; 70612 scaleLabelX = isLeft 70613 ? me.left + halfLineHeight + scaleLabelPadding.top 70614 : me.right - halfLineHeight - scaleLabelPadding.top; 70615 scaleLabelY = me.top + ((me.bottom - me.top) / 2); 70616 rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI; 70617 } 70618 70619 context.save(); 70620 context.translate(scaleLabelX, scaleLabelY); 70621 context.rotate(rotation); 70622 context.textAlign = 'center'; 70623 context.textBaseline = 'middle'; 70624 context.fillStyle = scaleLabelFontColor; // render in correct colour 70625 context.font = scaleLabelFont.string;
70626 context.fillText(scaleLabel.labelString, 0, 0); 70627 context.restore(); 70628 } 70629 70630 if (axisWidth) { 70631 // Draw the line at the edge of the axis 70632 var firstLineWidth = axisWidth; 70633 var lastLineWidth = valueAtIndexOrDefault(gridLines.lineWidth, ticks.length - 1, 0); 70634 var x1, x2, y1, y2; 70635 70636 if (isHorizontal) { 70637 x1 = alignPixel(chart, me.left, firstLineWidth) - firstLineWidth / 2; 70638 x2 = alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2; 70639 y1 = y2 = borderValue; 70640 } else { 70641 y1 = alignPixel(chart, me.top, firstLineWidth) - firstLineWidth / 2; 70642 y2 = alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; 70643 x1 = x2 = borderValue; 70644 } 70645 70646 context.lineWidth = axisWidth; 70647 context.strokeStyle = valueAtIndexOrDefault(gridLines.color, 0); 70648 context.beginPath(); 70649 context.moveTo(x1, y1); 70650 context.lineTo(x2, y2); 70651 context.stroke(); 70652 } 70653 } 70654}); 70655 70656var defaultConfig = { 70657 position: 'bottom' 70658}; 70659 70660var scale_category = core_scale.extend({ 70661 /** 70662 * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those 70663 * else fall back to data.labels 70664 * @private 70665 */ 70666 getLabels: function() { 70667 var data = this.chart.data; 70668 return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; 70669 }, 70670 70671 determineDataLimits: function() { 70672 var me = this; 70673 var labels = me.getLabels(); 70674 me.minIndex = 0; 70675 me.maxIndex = labels.length - 1; 70676 var findIndex; 70677 70678 if (me.options.ticks.min !== undefined) { 70679 // user specified min value 70680 findIndex = labels.indexOf(me.options.ticks.min); 70681 me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; 70682 } 70683 70684 if (me.options.ticks.max !== undefined) { 70685 // user specified max value 70686 findIndex = labels.indexOf(me.options.ticks.max); 70687 me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; 70688 } 70689 70690 me.min = labels[me.minIndex]; 70691 me.max = labels[me.maxIndex]; 70692 }, 70693 70694 buildTicks: function() { 70695 var me = this; 70696 var labels = me.getLabels(); 70697 // If we are viewing some subset of labels, slice the original array 70698 me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); 70699 }, 70700 70701 getLabelForIndex: function(index, datasetIndex) { 70702 var me = this; 70703 var chart = me.chart; 70704 70705 if (chart.getDatasetMeta(datasetIndex).controller._getValueScaleId() === me.id) { 70706 return me.getRightValue(chart.data.datasets[datasetIndex].data[index]); 70707 } 70708 70709 return me.ticks[index - me.minIndex]; 70710 }, 70711 70712 // Used to get data value locations. Value can either be an index or a numerical value 70713 getPixelForValue: function(value, index) { 70714 var me = this; 70715 var offset = me.options.offset; 70716 // 1 is added because we need the length but we have the indexes 70717 var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1); 70718 70719 // If value is a data object, then index is the index in the data array, 70720 // not the index of the scale. We need to change that. 70721 var valueCategory; 70722 if (value !== undefined && value !== null) { 70723 valueCategory = me.isHorizontal() ? value.x : value.y; 70724 } 70725 if (valueCategory !== undefined || (value !== undefined && isNaN(index))) { 70726 var labels = me.getLabels(); 70727 value = valueCategory || value; 70728 var idx = labels.indexOf(value); 70729 index = idx !== -1 ? idx : index; 70730 } 70731 70732 if (me.isHorizontal()) { 70733 var valueWidth = me.width / offsetAmt; 70734 var widthOffset = (valueWidth * (index - me.minIndex)); 70735 70736 if (offset) { 70737 widthOffset += (valueWidth / 2); 70738 } 70739 70740 return me.left + widthOffset; 70741 } 70742 var valueHeight = me.height / offsetAmt; 70743 var heightOffset = (valueHeight * (index - me.minIndex)); 70744 70745 if (offset) { 70746 heightOffset += (valueHeight / 2); 70747 } 70748 70749 return me.top + heightOffset; 70750 }, 70751 70752 getPixelForTick: function(index) { 70753 return this.getPixelForValue(this.ticks[index], index + this.minIndex, null); 70754 }, 70755 70756 getValueForPixel: function(pixel) { 70757 var me = this; 70758 var offset = me.options.offset; 70759 var value; 70760 var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1); 70761 var horz = me.isHorizontal(); 70762 var valueDimension = (horz ? me.width : me.height) / offsetAmt; 70763 70764 pixel -= horz ? me.left : me.top; 70765 70766 if (offset) { 70767 pixel -= (valueDimension / 2); 70768 } 70769 70770 if (pixel <= 0) { 70771 value = 0; 70772 } else { 70773 value = Math.round(pixel / valueDimension); 70774 } 70775 70776 return value + me.minIndex; 70777 }, 70778 70779 getBasePixel: function() { 70780 return this.bottom; 70781 } 70782}); 70783 70784// INTERNAL: static default options, registered in src/index.js 70785var _defaults = defaultConfig; 70786scale_category._defaults = _defaults; 70787 70788var noop = helpers$1.noop; 70789var isNullOrUndef = helpers$1.isNullOrUndef; 70790 70791/** 70792 * Generate a set of linear ticks 70793 * @param generationOptions the options used to generate the ticks 70794 * @param dataRange the range of the data 70795 * @returns {number[]} array of tick values 70796 */ 70797function generateTicks(generationOptions, dataRange) { 70798 var ticks = []; 70799 // To get a "nice" value for the tick spacing, we will use the appropriately named 70800 // "nice number" algorithm. See https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks 70801 // for details. 70802 70803 var MIN_SPACING = 1e-14; 70804 var stepSize = generationOptions.stepSize; 70805 var unit = stepSize || 1;
vendor: 5,384 bytes, lines 70806-70987
70806 var maxNumSpaces = generationOptions.maxTicks - 1; 70807 var min = generationOptions.min; 70808 var max = generationOptions.max; 70809 var precision = generationOptions.precision; 70810 var rmin = dataRange.min; 70811 var rmax = dataRange.max; 70812 var spacing = helpers$1.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit; 70813 var factor, niceMin, niceMax, numSpaces; 70814 70815 // Beyond MIN_SPACING floating point numbers being to lose precision 70816 // such that we can't do the math necessary to generate ticks 70817 if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) { 70818 return [rmin, rmax]; 70819 } 70820 70821 numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); 70822 if (numSpaces > maxNumSpaces) { 70823 // If the calculated num of spaces exceeds maxNumSpaces, recalculate it 70824 spacing = helpers$1.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit; 70825 } 70826 70827 if (stepSize || isNullOrUndef(precision)) { 70828 // If a precision is not specified, calculate factor based on spacing 70829 factor = Math.pow(10, helpers$1._decimalPlaces(spacing)); 70830 } else { 70831 // If the user specified a precision, round to that number of decimal places 70832 factor = Math.pow(10, precision); 70833 spacing = Math.ceil(spacing * factor) / factor; 70834 } 70835 70836 niceMin = Math.floor(rmin / spacing) * spacing; 70837 niceMax = Math.ceil(rmax / spacing) * spacing; 70838 70839 // If min, max and stepSize is set and they make an evenly spaced scale use it. 70840 if (stepSize) { 70841 // If very close to our whole number, use it. 70842 if (!isNullOrUndef(min) && helpers$1.almostWhole(min / spacing, spacing / 1000)) { 70843 niceMin = min; 70844 } 70845 if (!isNullOrUndef(max) && helpers$1.almostWhole(max / spacing, spacing / 1000)) { 70846 niceMax = max; 70847 } 70848 } 70849 70850 numSpaces = (niceMax - niceMin) / spacing; 70851 // If very close to our rounded value, use it. 70852 if (helpers$1.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { 70853 numSpaces = Math.round(numSpaces); 70854 } else { 70855 numSpaces = Math.ceil(numSpaces); 70856 } 70857 70858 niceMin = Math.round(niceMin * factor) / factor; 70859 niceMax = Math.round(niceMax * factor) / factor; 70860 ticks.push(isNullOrUndef(min) ? niceMin : min); 70861 for (var j = 1; j < numSpaces; ++j) { 70862 ticks.push(Math.round((niceMin + j * spacing) * factor) / factor); 70863 } 70864 ticks.push(isNullOrUndef(max) ? niceMax : max); 70865 70866 return ticks; 70867} 70868 70869var scale_linearbase = core_scale.extend({ 70870 getRightValue: function(value) { 70871 if (typeof value === 'string') { 70872 return +value; 70873 } 70874 return core_scale.prototype.getRightValue.call(this, value); 70875 }, 70876 70877 handleTickRangeOptions: function() { 70878 var me = this; 70879 var opts = me.options; 70880 var tickOpts = opts.ticks; 70881 70882 // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, 70883 // do nothing since that would make the chart weird. If the user really wants a weird chart 70884 // axis, they can manually override it 70885 if (tickOpts.beginAtZero) { 70886 var minSign = helpers$1.sign(me.min); 70887 var maxSign = helpers$1.sign(me.max); 70888 70889 if (minSign < 0 && maxSign < 0) { 70890 // move the top up to 0 70891 me.max = 0; 70892 } else if (minSign > 0 && maxSign > 0) { 70893 // move the bottom down to 0 70894 me.min = 0; 70895 } 70896 } 70897 70898 var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined; 70899 var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined; 70900 70901 if (tickOpts.min !== undefined) { 70902 me.min = tickOpts.min; 70903 } else if (tickOpts.suggestedMin !== undefined) { 70904 if (me.min === null) { 70905 me.min = tickOpts.suggestedMin; 70906 } else { 70907 me.min = Math.min(me.min, tickOpts.suggestedMin); 70908 } 70909 } 70910 70911 if (tickOpts.max !== undefined) { 70912 me.max = tickOpts.max; 70913 } else if (tickOpts.suggestedMax !== undefined) { 70914 if (me.max === null) { 70915 me.max = tickOpts.suggestedMax; 70916 } else { 70917 me.max = Math.max(me.max, tickOpts.suggestedMax); 70918 } 70919 } 70920 70921 if (setMin !== setMax) { 70922 // We set the min or the max but not both. 70923 // So ensure that our range is good 70924 // Inverted or 0 length range can happen when 70925 // ticks.min is set, and no datasets are visible 70926 if (me.min >= me.max) { 70927 if (setMin) { 70928 me.max = me.min + 1; 70929 } else { 70930 me.min = me.max - 1; 70931 } 70932 } 70933 } 70934 70935 if (me.min === me.max) { 70936 me.max++; 70937 70938 if (!tickOpts.beginAtZero) { 70939 me.min--; 70940 } 70941 } 70942 }, 70943 70944 getTickLimit: function() { 70945 var me = this; 70946 var tickOpts = me.options.ticks; 70947 var stepSize = tickOpts.stepSize; 70948 var maxTicksLimit = tickOpts.maxTicksLimit; 70949 var maxTicks; 70950 70951 if (stepSize) { 70952 maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1; 70953 } else { 70954 maxTicks = me._computeTickLimit(); 70955 maxTicksLimit = maxTicksLimit || 11; 70956 } 70957 70958 if (maxTicksLimit) { 70959 maxTicks = Math.min(maxTicksLimit, maxTicks); 70960 } 70961 70962 return maxTicks; 70963 }, 70964 70965 _computeTickLimit: function() { 70966 return Number.POSITIVE_INFINITY; 70967 }, 70968 70969 handleDirectionalChanges: noop, 70970 70971 buildTicks: function() { 70972 var me = this; 70973 var opts = me.options; 70974 var tickOpts = opts.ticks; 70975 70976 // Figure out what the max number of ticks we can support it is based on the size of 70977 // the axis area. For now, we say that the minimum tick spacing in pixels must be 40 70978 // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on 70979 // the graph. Make sure we always have at least 2 ticks 70980 var maxTicks = me.getTickLimit(); 70981 maxTicks = Math.max(2, maxTicks); 70982 70983 var numericGeneratorOptions = { 70984 maxTicks: maxTicks, 70985 min: tickOpts.min, 70986 max: tickOpts.max, 70987 precision: tickOpts.precision,
70988 stepSize: helpers$1.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) 70989 }; 70990 var ticks = me.ticks = generateTicks(numericGeneratorOptions, me); 70991 70992 me.handleDirectionalChanges(); 70993 70994 // At this point, we need to update our max and min given the tick values since we have expanded the 70995 // range of the scale 70996 me.max = helpers$1.max(ticks); 70997 me.min = helpers$1.min(ticks); 70998 70999 if (tickOpts.reverse) { 71000 ticks.reverse(); 71001 71002 me.start = me.max; 71003 me.end = me.min; 71004 } else { 71005 me.start = me.min; 71006 me.end = me.max; 71007 } 71008 }, 71009 71010 convertTicksToLabels: function() { 71011 var me = this; 71012 me.ticksAsNumbers = me.ticks.slice(); 71013 me.zeroLineIndex = me.ticks.indexOf(0); 71014 71015 core_scale.prototype.convertTicksToLabels.call(me); 71016 } 71017}); 71018 71019var defaultConfig$1 = { 71020 position: 'left', 71021 ticks: { 71022 callback: core_ticks.formatters.linear 71023 } 71024}; 71025 71026var scale_linear = scale_linearbase.extend({ 71027 determineDataLimits: function() { 71028 var me = this; 71029 var opts = me.options; 71030 var chart = me.chart; 71031 var data = chart.data; 71032 var datasets = data.datasets; 71033 var isHorizontal = me.isHorizontal(); 71034 var DEFAULT_MIN = 0; 71035 var DEFAULT_MAX = 1; 71036 71037 function IDMatches(meta) { 71038 return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; 71039 } 71040 71041 // First Calculate the range 71042 me.min = null; 71043 me.max = null; 71044 71045 var hasStacks = opts.stacked; 71046 if (hasStacks === undefined) { 71047 helpers$1.each(datasets, function(dataset, datasetIndex) { 71048 if (hasStacks) { 71049 return; 71050 } 71051 71052 var meta = chart.getDatasetMeta(datasetIndex); 71053 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && 71054 meta.stack !== undefined) { 71055 hasStacks = true; 71056 } 71057 }); 71058 } 71059 71060 if (opts.stacked || hasStacks) { 71061 var valuesPerStack = {}; 71062 71063 helpers$1.each(datasets, function(dataset, datasetIndex) { 71064 var meta = chart.getDatasetMeta(datasetIndex); 71065 var key = [ 71066 meta.type, 71067 // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined 71068 ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), 71069 meta.stack 71070 ].join('.'); 71071 71072 if (valuesPerStack[key] === undefined) { 71073 valuesPerStack[key] = { 71074 positiveValues: [], 71075 negativeValues: [] 71076 }; 71077 } 71078 71079 // Store these per type 71080 var positiveValues = valuesPerStack[key].positiveValues; 71081 var negativeValues = valuesPerStack[key].negativeValues; 71082 71083 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { 71084 helpers$1.each(dataset.data, function(rawValue, index) { 71085 var value = +me.getRightValue(rawValue); 71086 if (isNaN(value) || meta.data[index].hidden) { 71087 return; 71088 } 71089 71090 positiveValues[index] = positiveValues[index] || 0; 71091 negativeValues[index] = negativeValues[index] || 0; 71092 71093 if (opts.relativePoints) { 71094 positiveValues[index] = 100; 71095 } else if (value < 0) { 71096 negativeValues[index] += value; 71097 } else { 71098 positiveValues[index] += value; 71099 } 71100 }); 71101 } 71102 }); 71103 71104 helpers$1.each(valuesPerStack, function(valuesForType) { 71105 var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); 71106 var minVal = helpers$1.min(values); 71107 var maxVal = helpers$1.max(values); 71108 me.min = me.min === null ? minVal : Math.min(me.min, minVal); 71109 me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); 71110 }); 71111 71112 } else { 71113 helpers$1.each(datasets, function(dataset, datasetIndex) { 71114 var meta = chart.getDatasetMeta(datasetIndex); 71115 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { 71116 helpers$1.each(dataset.data, function(rawValue, index) { 71117 var value = +me.getRightValue(rawValue); 71118 if (isNaN(value) || meta.data[index].hidden) { 71119 return; 71120 } 71121 71122 if (me.min === null) { 71123 me.min = value; 71124 } else if (value < me.min) { 71125 me.min = value; 71126 } 71127 71128 if (me.max === null) { 71129 me.max = value; 71130 } else if (value > me.max) { 71131 me.max = value; 71132 } 71133 }); 71134 } 71135 }); 71136 } 71137 71138 me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN; 71139 me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX; 71140 71141 // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero 71142 this.handleTickRangeOptions(); 71143 }, 71144 71145 // Returns the maximum number of ticks based on the scale dimension 71146 _computeTickLimit: function() { 71147 var me = this;
71148 var tickFont; 71149 71150 if (me.isHorizontal()) { 71151 return Math.ceil(me.width / 40); 71152 } 71153 tickFont = helpers$1.options._parseFont(me.options.ticks); 71154 return Math.ceil(me.height / tickFont.lineHeight); 71155 }, 71156 71157 // Called after the ticks are built. We need 71158 handleDirectionalChanges: function() { 71159 if (!this.isHorizontal()) { 71160 // We are in a vertical orientation. The top value is the highest. So reverse the array 71161 this.ticks.reverse(); 71162 } 71163 }, 71164 71165 getLabelForIndex: function(index, datasetIndex) { 71166 return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); 71167 }, 71168 71169 // Utils 71170 getPixelForValue: function(value) { 71171 // This must be called after fit has been run so that 71172 // this.left, this.top, this.right, and this.bottom have been defined 71173 var me = this; 71174 var start = me.start; 71175 71176 var rightValue = +me.getRightValue(value); 71177 var pixel; 71178 var range = me.end - start; 71179 71180 if (me.isHorizontal()) { 71181 pixel = me.left + (me.width / range * (rightValue - start)); 71182 } else { 71183 pixel = me.bottom - (me.height / range * (rightValue - start)); 71184 } 71185 return pixel; 71186 }, 71187 71188 getValueForPixel: function(pixel) { 71189 var me = this; 71190 var isHorizontal = me.isHorizontal(); 71191 var innerDimension = isHorizontal ? me.width : me.height; 71192 var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension; 71193 return me.start + ((me.end - me.start) * offset); 71194 }, 71195 71196 getPixelForTick: function(index) { 71197 return this.getPixelForValue(this.ticksAsNumbers[index]); 71198 } 71199}); 71200 71201// INTERNAL: static default options, registered in src/index.js 71202var _defaults$1 = defaultConfig$1; 71203scale_linear._defaults = _defaults$1; 71204 71205var valueOrDefault$a = helpers$1.valueOrDefault; 71206 71207/** 71208 * Generate a set of logarithmic ticks 71209 * @param generationOptions the options used to generate the ticks 71210 * @param dataRange the range of the data 71211 * @returns {number[]} array of tick values 71212 */ 71213function generateTicks$1(generationOptions, dataRange) { 71214 var ticks = []; 71215 71216 var tickVal = valueOrDefault$a(generationOptions.min, Math.pow(10, Math.floor(helpers$1.log10(dataRange.min)))); 71217 71218 var endExp = Math.floor(helpers$1.log10(dataRange.max)); 71219 var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); 71220 var exp, significand; 71221 71222 if (tickVal === 0) { 71223 exp = Math.floor(helpers$1.log10(dataRange.minNotZero)); 71224 significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); 71225 71226 ticks.push(tickVal); 71227 tickVal = significand * Math.pow(10, exp); 71228 } else { 71229 exp = Math.floor(helpers$1.log10(tickVal)); 71230 significand = Math.floor(tickVal / Math.pow(10, exp)); 71231 } 71232 var precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1; 71233 71234 do { 71235 ticks.push(tickVal); 71236 71237 ++significand; 71238 if (significand === 10) { 71239 significand = 1; 71240 ++exp; 71241 precision = exp >= 0 ? 1 : precision; 71242 } 71243 71244 tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision; 71245 } while (exp < endExp || (exp === endExp && significand < endSignificand)); 71246 71247 var lastTick = valueOrDefault$a(generationOptions.max, tickVal); 71248 ticks.push(lastTick); 71249 71250 return ticks; 71251} 71252 71253var defaultConfig$2 = { 71254 position: 'left', 71255 71256 // label settings 71257 ticks: { 71258 callback: core_ticks.formatters.logarithmic 71259 } 71260}; 71261 71262// TODO(v3): change this to positiveOrDefault 71263function nonNegativeOrDefault(value, defaultValue) { 71264 return helpers$1.isFinite(value) && value >= 0 ? value : defaultValue; 71265} 71266 71267var scale_logarithmic = core_scale.extend({ 71268 determineDataLimits: function() { 71269 var me = this; 71270 var opts = me.options; 71271 var chart = me.chart; 71272 var data = chart.data; 71273 var datasets = data.datasets; 71274 var isHorizontal = me.isHorizontal(); 71275 function IDMatches(meta) { 71276 return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; 71277 } 71278 71279 // Calculate Range 71280 me.min = null; 71281 me.max = null; 71282 me.minNotZero = null; 71283 71284 var hasStacks = opts.stacked; 71285 if (hasStacks === undefined) { 71286 helpers$1.each(datasets, function(dataset, datasetIndex) { 71287 if (hasStacks) { 71288 return; 71289 } 71290 71291 var meta = chart.getDatasetMeta(datasetIndex); 71292 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && 71293 meta.stack !== undefined) { 71294 hasStacks = true; 71295 } 71296 }); 71297 } 71298 71299 if (opts.stacked || hasStacks) { 71300 var valuesPerStack = {}; 71301 71302 helpers$1.each(datasets, function(dataset, datasetIndex) { 71303 var meta = chart.getDatasetMeta(datasetIndex); 71304 var key = [ 71305 meta.type, 71306 // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined 71307 ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), 71308 meta.stack 71309 ].join('.'); 71310 71311 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { 71312 if (valuesPerStack[key] === undefined) { 71313 valuesPerStack[key] = []; 71314 } 71315 71316 helpers$1.each(dataset.data, function(rawValue, index) { 71317 var values = valuesPerStack[key]; 71318 var value = +me.getRightValue(rawValue); 71319 // invalid, hidden and negative values are ignored 71320 if (isNaN(value) || meta.data[index].hidden || value < 0) { 71321 return; 71322 } 71323 values[index] = values[index] || 0; 71324 values[index] += value; 71325 }); 71326 } 71327 }); 71328 71329 helpers$1.each(valuesPerStack, function(valuesForType) { 71330 if (valuesForType.length > 0) { 71331 var minVal = helpers$1.min(valuesForType); 71332 var maxVal = helpers$1.max(valuesForType); 71333 me.min = me.min === null ? minVal : Math.min(me.min, minVal); 71334 me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); 71335 } 71336 }); 71337 71338 } else { 71339 helpers$1.each(datasets, function(dataset, datasetIndex) { 71340 var meta = chart.getDatasetMeta(datasetIndex); 71341 if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { 71342 helpers$1.each(dataset.data, function(rawValue, index) { 71343 var value = +me.getRightValue(rawValue); 71344 // invalid, hidden and negative values are ignored 71345 if (isNaN(value) || meta.data[index].hidden || value < 0) { 71346 return; 71347 } 71348 71349 if (me.min === null) { 71350 me.min = value; 71351 } else if (value < me.min) { 71352 me.min = value; 71353 } 71354 71355 if (me.max === null) { 71356 me.max = value; 71357 } else if (value > me.max) { 71358 me.max = value; 71359 } 71360 71361 if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) { 71362 me.minNotZero = value; 71363 } 71364 }); 71365 } 71366 }); 71367 } 71368 71369 // Common base implementation to handle ticks.min, ticks.max 71370 this.handleTickRangeOptions(); 71371 }, 71372 71373 handleTickRangeOptions: function() { 71374 var me = this; 71375 var tickOpts = me.options.ticks; 71376 var DEFAULT_MIN = 1; 71377 var DEFAULT_MAX = 10; 71378 71379 me.min = nonNegativeOrDefault(tickOpts.min, me.min); 71380 me.max = nonNegativeOrDefault(tickOpts.max, me.max); 71381 71382 if (me.min === me.max) { 71383 if (me.min !== 0 && me.min !== null) {
71384 me.min = Math.pow(10, Math.floor(helpers$1.log10(me.min)) - 1); 71385 me.max = Math.pow(10, Math.floor(helpers$1.log10(me.max)) + 1); 71386 } else { 71387 me.min = DEFAULT_MIN; 71388 me.max = DEFAULT_MAX; 71389 } 71390 } 71391 if (me.min === null) { 71392 me.min = Math.pow(10, Math.floor(helpers$1.log10(me.max)) - 1); 71393 } 71394 if (me.max === null) { 71395 me.max = me.min !== 0 71396 ? Math.pow(10, Math.floor(helpers$1.log10(me.min)) + 1) 71397 : DEFAULT_MAX; 71398 } 71399 if (me.minNotZero === null) { 71400 if (me.min > 0) { 71401 me.minNotZero = me.min; 71402 } else if (me.max < 1) { 71403 me.minNotZero = Math.pow(10, Math.floor(helpers$1.log10(me.max))); 71404 } else { 71405 me.minNotZero = DEFAULT_MIN; 71406 } 71407 } 71408 }, 71409 71410 buildTicks: function() { 71411 var me = this; 71412 var tickOpts = me.options.ticks; 71413 var reverse = !me.isHorizontal(); 71414 71415 var generationOptions = { 71416 min: nonNegativeOrDefault(tickOpts.min), 71417 max: nonNegativeOrDefault(tickOpts.max) 71418 }; 71419 var ticks = me.ticks = generateTicks$1(generationOptions, me); 71420 71421 // At this point, we need to update our max and min given the tick values since we have expanded the 71422 // range of the scale 71423 me.max = helpers$1.max(ticks); 71424 me.min = helpers$1.min(ticks); 71425 71426 if (tickOpts.reverse) { 71427 reverse = !reverse; 71428 me.start = me.max; 71429 me.end = me.min; 71430 } else { 71431 me.start = me.min; 71432 me.end = me.max; 71433 } 71434 if (reverse) { 71435 ticks.reverse(); 71436 } 71437 }, 71438 71439 convertTicksToLabels: function() { 71440 this.tickValues = this.ticks.slice(); 71441 71442 core_scale.prototype.convertTicksToLabels.call(this); 71443 }, 71444 71445 // Get the correct tooltip label 71446 getLabelForIndex: function(index, datasetIndex) { 71447 return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); 71448 }, 71449 71450 getPixelForTick: function(index) { 71451 return this.getPixelForValue(this.tickValues[index]); 71452 }, 71453 71454 /** 71455 * Returns the value of the first tick. 71456 * @param {number} value - The minimum not zero value. 71457 * @return {number} The first tick value. 71458 * @private 71459 */ 71460 _getFirstTickValue: function(value) { 71461 var exp = Math.floor(helpers$1.log10(value)); 71462 var significand = Math.floor(value / Math.pow(10, exp)); 71463 71464 return significand * Math.pow(10, exp); 71465 }, 71466 71467 getPixelForValue: function(value) { 71468 var me = this; 71469 var tickOpts = me.options.ticks; 71470 var reverse = tickOpts.reverse; 71471 var log10 = helpers$1.log10; 71472 var firstTickValue = me._getFirstTickValue(me.minNotZero); 71473 var offset = 0; 71474 var innerDimension, pixel, start, end, sign; 71475 71476 value = +me.getRightValue(value); 71477 if (reverse) { 71478 start = me.end; 71479 end = me.start; 71480 sign = -1; 71481 } else { 71482 start = me.start; 71483 end = me.end; 71484 sign = 1; 71485 } 71486 if (me.isHorizontal()) { 71487 innerDimension = me.width; 71488 pixel = reverse ? me.right : me.left; 71489 } else { 71490 innerDimension = me.height; 71491 sign *= -1; // invert, since the upper-left corner of the canvas is at pixel (0, 0) 71492 pixel = reverse ? me.top : me.bottom; 71493 } 71494 if (value !== start) { 71495 if (start === 0) { // include zero tick 71496 offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize); 71497 innerDimension -= offset; 71498 start = firstTickValue; 71499 } 71500 if (value !== 0) { 71501 offset += innerDimension / (log10(end) - log10(start)) * (log10(value) - log10(start)); 71502 } 71503 pixel += sign * offset; 71504 } 71505 return pixel; 71506 }, 71507 71508 getValueForPixel: function(pixel) { 71509 var me = this; 71510 var tickOpts = me.options.ticks; 71511 var reverse = tickOpts.reverse; 71512 var log10 = helpers$1.log10; 71513 var firstTickValue = me._getFirstTickValue(me.minNotZero); 71514 var innerDimension, start, end, value; 71515 71516 if (reverse) { 71517 start = me.end; 71518 end = me.start; 71519 } else { 71520 start = me.start; 71521 end = me.end; 71522 } 71523 if (me.isHorizontal()) { 71524 innerDimension = me.width; 71525 value = reverse ? me.right - pixel : pixel - me.left; 71526 } else { 71527 innerDimension = me.height; 71528 value = reverse ? pixel - me.top : me.bottom - pixel; 71529 } 71530 if (value !== start) { 71531 if (start === 0) { // include zero tick 71532 var offset = valueOrDefault$a(tickOpts.fontSize, core_defaults.global.defaultFontSize); 71533 value -= offset; 71534 innerDimension -= offset; 71535 start = firstTickValue; 71536 } 71537 value *= log10(end) - log10(start); 71538 value /= innerDimension; 71539 value = Math.pow(10, log10(start) + value); 71540 } 71541 return value; 71542 } 71543}); 71544 71545// INTERNAL: static default options, registered in src/index.js 71546var _defaults$2 = defaultConfig$2; 71547scale_logarithmic._defaults = _defaults$2; 71548 71549var valueOrDefault$b = helpers$1.valueOrDefault; 71550var valueAtIndexOrDefault$1 = helpers$1.valueAtIndexOrDefault; 71551var resolve$7 = helpers$1.options.resolve; 71552 71553var defaultConfig$3 = {
vendor: 11,713 bytes, lines 71554-71950
71554 display: true, 71555 71556 // Boolean - Whether to animate scaling the chart from the centre 71557 animate: true, 71558 position: 'chartArea', 71559 71560 angleLines: { 71561 display: true, 71562 color: 'rgba(0, 0, 0, 0.1)', 71563 lineWidth: 1, 71564 borderDash: [], 71565 borderDashOffset: 0.0 71566 }, 71567 71568 gridLines: { 71569 circular: false 71570 }, 71571 71572 // label settings 71573 ticks: { 71574 // Boolean - Show a backdrop to the scale label 71575 showLabelBackdrop: true, 71576 71577 // String - The colour of the label backdrop 71578 backdropColor: 'rgba(255,255,255,0.75)', 71579 71580 // Number - The backdrop padding above & below the label in pixels 71581 backdropPaddingY: 2, 71582 71583 // Number - The backdrop padding to the side of the label in pixels 71584 backdropPaddingX: 2, 71585 71586 callback: core_ticks.formatters.linear 71587 }, 71588 71589 pointLabels: { 71590 // Boolean - if true, show point labels 71591 display: true, 71592 71593 // Number - Point label font size in pixels 71594 fontSize: 10, 71595 71596 // Function - Used to convert point labels 71597 callback: function(label) { 71598 return label; 71599 } 71600 } 71601}; 71602 71603function getValueCount(scale) { 71604 var opts = scale.options; 71605 return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0; 71606} 71607 71608function getTickBackdropHeight(opts) { 71609 var tickOpts = opts.ticks; 71610 71611 if (tickOpts.display && opts.display) { 71612 return valueOrDefault$b(tickOpts.fontSize, core_defaults.global.defaultFontSize) + tickOpts.backdropPaddingY * 2; 71613 } 71614 return 0; 71615} 71616 71617function measureLabelSize(ctx, lineHeight, label) { 71618 if (helpers$1.isArray(label)) { 71619 return { 71620 w: helpers$1.longestText(ctx, ctx.font, label), 71621 h: label.length * lineHeight 71622 }; 71623 } 71624 71625 return { 71626 w: ctx.measureText(label).width, 71627 h: lineHeight 71628 }; 71629} 71630 71631function determineLimits(angle, pos, size, min, max) { 71632 if (angle === min || angle === max) { 71633 return { 71634 start: pos - (size / 2), 71635 end: pos + (size / 2) 71636 }; 71637 } else if (angle < min || angle > max) { 71638 return { 71639 start: pos - size, 71640 end: pos 71641 }; 71642 } 71643 71644 return { 71645 start: pos, 71646 end: pos + size 71647 }; 71648} 71649 71650/** 71651 * Helper function to fit a radial linear scale with point labels 71652 */ 71653function fitWithPointLabels(scale) { 71654 71655 // Right, this is really confusing and there is a lot of maths going on here 71656 // The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 71657 // 71658 // Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif 71659 // 71660 // Solution: 71661 // 71662 // We assume the radius of the polygon is half the size of the canvas at first 71663 // at each index we check if the text overlaps. 71664 // 71665 // Where it does, we store that angle and that index. 71666 // 71667 // After finding the largest index and angle we calculate how much we need to remove 71668 // from the shape radius to move the point inwards by that x. 71669 // 71670 // We average the left and right distances to get the maximum shape radius that can fit in the box 71671 // along with labels. 71672 // 71673 // Once we have that, we can find the centre point for the chart, by taking the x text protrusion 71674 // on each side, removing that from the size, halving it and adding the left x protrusion width. 71675 // 71676 // This will mean we have a shape fitted to the canvas, as large as it can be with the labels 71677 // and position it in the most space efficient manner 71678 // 71679 // https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif 71680 71681 var plFont = helpers$1.options._parseFont(scale.options.pointLabels); 71682 71683 // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. 71684 // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points 71685 var furthestLimits = { 71686 l: 0, 71687 r: scale.width, 71688 t: 0, 71689 b: scale.height - scale.paddingTop 71690 }; 71691 var furthestAngles = {}; 71692 var i, textSize, pointPosition; 71693 71694 scale.ctx.font = plFont.string; 71695 scale._pointLabelSizes = []; 71696 71697 var valueCount = getValueCount(scale); 71698 for (i = 0; i < valueCount; i++) { 71699 pointPosition = scale.getPointPosition(i, scale.drawingArea + 5); 71700 textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale.pointLabels[i] || ''); 71701 scale._pointLabelSizes[i] = textSize; 71702 71703 // Add quarter circle to make degree 0 mean top of circle 71704 var angleRadians = scale.getIndexAngle(i); 71705 var angle = helpers$1.toDegrees(angleRadians) % 360; 71706 var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); 71707 var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); 71708 71709 if (hLimits.start < furthestLimits.l) { 71710 furthestLimits.l = hLimits.start; 71711 furthestAngles.l = angleRadians; 71712 } 71713 71714 if (hLimits.end > furthestLimits.r) { 71715 furthestLimits.r = hLimits.end; 71716 furthestAngles.r = angleRadians; 71717 } 71718 71719 if (vLimits.start < furthestLimits.t) { 71720 furthestLimits.t = vLimits.start; 71721 furthestAngles.t = angleRadians; 71722 } 71723 71724 if (vLimits.end > furthestLimits.b) { 71725 furthestLimits.b = vLimits.end; 71726 furthestAngles.b = angleRadians; 71727 } 71728 } 71729 71730 scale.setReductions(scale.drawingArea, furthestLimits, furthestAngles); 71731} 71732 71733function getTextAlignForAngle(angle) { 71734 if (angle === 0 || angle === 180) { 71735 return 'center'; 71736 } else if (angle < 180) { 71737 return 'left'; 71738 } 71739 71740 return 'right'; 71741} 71742 71743function fillText(ctx, text, position, lineHeight) { 71744 var y = position.y + lineHeight / 2; 71745 var i, ilen; 71746 71747 if (helpers$1.isArray(text)) { 71748 for (i = 0, ilen = text.length; i < ilen; ++i) { 71749 ctx.fillText(text[i], position.x, y); 71750 y += lineHeight; 71751 } 71752 } else { 71753 ctx.fillText(text, position.x, y); 71754 } 71755} 71756 71757function adjustPointPositionForLabelHeight(angle, textSize, position) { 71758 if (angle === 90 || angle === 270) { 71759 position.y -= (textSize.h / 2); 71760 } else if (angle > 270 || angle < 90) { 71761 position.y -= textSize.h; 71762 } 71763} 71764 71765function drawPointLabels(scale) { 71766 var ctx = scale.ctx; 71767 var opts = scale.options; 71768 var angleLineOpts = opts.angleLines; 71769 var gridLineOpts = opts.gridLines; 71770 var pointLabelOpts = opts.pointLabels; 71771 var lineWidth = valueOrDefault$b(angleLineOpts.lineWidth, gridLineOpts.lineWidth); 71772 var lineColor = valueOrDefault$b(angleLineOpts.color, gridLineOpts.color); 71773 var tickBackdropHeight = getTickBackdropHeight(opts); 71774 71775 ctx.save(); 71776 ctx.lineWidth = lineWidth; 71777 ctx.strokeStyle = lineColor; 71778 if (ctx.setLineDash) { 71779 ctx.setLineDash(resolve$7([angleLineOpts.borderDash, gridLineOpts.borderDash, []])); 71780 ctx.lineDashOffset = resolve$7([angleLineOpts.borderDashOffset, gridLineOpts.borderDashOffset, 0.0]); 71781 } 71782 71783 var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max); 71784 71785 // Point Label Font 71786 var plFont = helpers$1.options._parseFont(pointLabelOpts); 71787 71788 ctx.font = plFont.string; 71789 ctx.textBaseline = 'middle'; 71790 71791 for (var i = getValueCount(scale) - 1; i >= 0; i--) { 71792 if (angleLineOpts.display && lineWidth && lineColor) { 71793 var outerPosition = scale.getPointPosition(i, outerDistance); 71794 ctx.beginPath(); 71795 ctx.moveTo(scale.xCenter, scale.yCenter); 71796 ctx.lineTo(outerPosition.x, outerPosition.y); 71797 ctx.stroke(); 71798 } 71799 71800 if (pointLabelOpts.display) { 71801 // Extra pixels out for some label spacing 71802 var extra = (i === 0 ? tickBackdropHeight / 2 : 0); 71803 var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5); 71804 71805 // Keep this in loop since we may support array properties here 71806 var pointLabelFontColor = valueAtIndexOrDefault$1(pointLabelOpts.fontColor, i, core_defaults.global.defaultFontColor); 71807 ctx.fillStyle = pointLabelFontColor; 71808 71809 var angleRadians = scale.getIndexAngle(i); 71810 var angle = helpers$1.toDegrees(angleRadians); 71811 ctx.textAlign = getTextAlignForAngle(angle); 71812 adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); 71813 fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.lineHeight); 71814 } 71815 } 71816 ctx.restore(); 71817} 71818 71819function drawRadiusLine(scale, gridLineOpts, radius, index) { 71820 var ctx = scale.ctx; 71821 var circular = gridLineOpts.circular; 71822 var valueCount = getValueCount(scale); 71823 var lineColor = valueAtIndexOrDefault$1(gridLineOpts.color, index - 1); 71824 var lineWidth = valueAtIndexOrDefault$1(gridLineOpts.lineWidth, index - 1); 71825 var pointPosition; 71826 71827 if ((!circular && !valueCount) || !lineColor || !lineWidth) { 71828 return; 71829 } 71830 71831 ctx.save(); 71832 ctx.strokeStyle = lineColor; 71833 ctx.lineWidth = lineWidth; 71834 if (ctx.setLineDash) { 71835 ctx.setLineDash(gridLineOpts.borderDash || []); 71836 ctx.lineDashOffset = gridLineOpts.borderDashOffset || 0.0; 71837 } 71838 71839 ctx.beginPath(); 71840 if (circular) { 71841 // Draw circular arcs between the points 71842 ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); 71843 } else { 71844 // Draw straight lines connecting each index 71845 pointPosition = scale.getPointPosition(0, radius); 71846 ctx.moveTo(pointPosition.x, pointPosition.y); 71847 71848 for (var i = 1; i < valueCount; i++) { 71849 pointPosition = scale.getPointPosition(i, radius); 71850 ctx.lineTo(pointPosition.x, pointPosition.y); 71851 } 71852 } 71853 ctx.closePath(); 71854 ctx.stroke(); 71855 ctx.restore(); 71856} 71857 71858function numberOrZero(param) { 71859 return helpers$1.isNumber(param) ? param : 0; 71860} 71861 71862var scale_radialLinear = scale_linearbase.extend({ 71863 setDimensions: function() { 71864 var me = this; 71865 71866 // Set the unconstrained dimension before label rotation 71867 me.width = me.maxWidth; 71868 me.height = me.maxHeight; 71869 me.paddingTop = getTickBackdropHeight(me.options) / 2; 71870 me.xCenter = Math.floor(me.width / 2); 71871 me.yCenter = Math.floor((me.height - me.paddingTop) / 2); 71872 me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2; 71873 }, 71874 71875 determineDataLimits: function() { 71876 var me = this; 71877 var chart = me.chart; 71878 var min = Number.POSITIVE_INFINITY; 71879 var max = Number.NEGATIVE_INFINITY; 71880 71881 helpers$1.each(chart.data.datasets, function(dataset, datasetIndex) { 71882 if (chart.isDatasetVisible(datasetIndex)) { 71883 var meta = chart.getDatasetMeta(datasetIndex); 71884 71885 helpers$1.each(dataset.data, function(rawValue, index) { 71886 var value = +me.getRightValue(rawValue); 71887 if (isNaN(value) || meta.data[index].hidden) { 71888 return; 71889 } 71890 71891 min = Math.min(value, min); 71892 max = Math.max(value, max); 71893 }); 71894 } 71895 }); 71896 71897 me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); 71898 me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); 71899 71900 // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero 71901 me.handleTickRangeOptions(); 71902 }, 71903 71904 // Returns the maximum number of ticks based on the scale dimension 71905 _computeTickLimit: function() { 71906 return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); 71907 }, 71908 71909 convertTicksToLabels: function() { 71910 var me = this; 71911 71912 scale_linearbase.prototype.convertTicksToLabels.call(me); 71913 71914 // Point labels 71915 me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); 71916 }, 71917 71918 getLabelForIndex: function(index, datasetIndex) { 71919 return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); 71920 }, 71921 71922 fit: function() { 71923 var me = this; 71924 var opts = me.options; 71925 71926 if (opts.display && opts.pointLabels.display) { 71927 fitWithPointLabels(me); 71928 } else { 71929 me.setCenterPoint(0, 0, 0, 0); 71930 } 71931 }, 71932 71933 /** 71934 * Set radius reductions and determine new radius and center point 71935 * @private 71936 */ 71937 setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { 71938 var me = this; 71939 var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); 71940 var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); 71941 var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); 71942 var radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b); 71943 71944 radiusReductionLeft = numberOrZero(radiusReductionLeft); 71945 radiusReductionRight = numberOrZero(radiusReductionRight); 71946 radiusReductionTop = numberOrZero(radiusReductionTop); 71947 radiusReductionBottom = numberOrZero(radiusReductionBottom); 71948 71949 me.drawingArea = Math.min( 71950 Math.floor(largestPossibleRadius - (radiusReductionLeft + radiu
71950sReductionRight) / 2), 71951 Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); 71952 me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); 71953 }, 71954 71955 setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { 71956 var me = this; 71957 var maxRight = me.width - rightMovement - me.drawingArea; 71958 var maxLeft = leftMovement + me.drawingArea; 71959 var maxTop = topMovement + me.drawingArea; 71960 var maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea; 71961 71962 me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left); 71963 me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop); 71964 }, 71965 71966 getIndexAngle: function(index) { 71967 var angleMultiplier = (Math.PI * 2) / getValueCount(this); 71968 var startAngle = this.chart.options && this.chart.options.startAngle ? 71969 this.chart.options.startAngle : 71970 0; 71971 71972 var startAngleRadians = startAngle * Math.PI * 2 / 360; 71973 71974 // Start from the top instead of right, so remove a quarter of the circle 71975 return index * angleMultiplier + startAngleRadians; 71976 }, 71977 71978 getDistanceFromCenterForValue: function(value) { 71979 var me = this; 71980 71981 if (value === null) { 71982 return 0; // null always in center 71983 } 71984 71985 // Take into account half font size + the yPadding of the top value 71986 var scalingFactor = me.drawingArea / (me.max - me.min); 71987 if (me.options.ticks.reverse) { 71988 return (me.max - value) * scalingFactor; 71989 } 71990 return (value - me.min) * scalingFactor; 71991 }, 71992 71993 getPointPosition: function(index, distanceFromCenter) { 71994 var me = this; 71995 var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); 71996 return { 71997 x: Math.cos(thisAngle) * distanceFromCenter + me.xCenter, 71998 y: Math.sin(thisAngle) * distanceFromCenter + me.yCenter 71999 }; 72000 }, 72001 72002 getPointPositionForValue: function(index, value) { 72003 return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); 72004 }, 72005 72006 getBasePosition: function() { 72007 var me = this; 72008 var min = me.min; 72009 var max = me.max; 72010 72011 return me.getPointPositionForValue(0, 72012 me.beginAtZero ? 0 : 72013 min < 0 && max < 0 ? max : 72014 min > 0 && max > 0 ? min : 72015 0); 72016 }, 72017 72018 draw: function() { 72019 var me = this; 72020 var opts = me.options; 72021 var gridLineOpts = opts.gridLines; 72022 var tickOpts = opts.ticks; 72023 72024 if (opts.display) { 72025 var ctx = me.ctx; 72026 var startAngle = this.getIndexAngle(0); 72027 var tickFont = helpers$1.options._parseFont(tickOpts); 72028 72029 if (opts.angleLines.display || opts.pointLabels.display) { 72030 drawPointLabels(me); 72031 } 72032 72033 helpers$1.each(me.ticks, function(label, index) { 72034 // Don't draw a centre value (if it is minimum) 72035 if (index > 0 || tickOpts.reverse) { 72036 var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); 72037 72038 // Draw circular lines around the scale 72039 if (gridLineOpts.display && index !== 0) { 72040 drawRadiusLine(me, gridLineOpts, yCenterOffset, index); 72041 } 72042 72043 if (tickOpts.display) { 72044 var tickFontColor = valueOrDefault$b(tickOpts.fontColor, core_defaults.global.defaultFontColor); 72045 ctx.font = tickFont.string; 72046 72047 ctx.save(); 72048 ctx.translate(me.xCenter, me.yCenter); 72049 ctx.rotate(startAngle); 72050 72051 if (tickOpts.showLabelBackdrop) { 72052 var labelWidth = ctx.measureText(label).width; 72053 ctx.fillStyle = tickOpts.backdropColor; 72054 ctx.fillRect( 72055 -labelWidth / 2 - tickOpts.backdropPaddingX, 72056 -yCenterOffset - tickFont.size / 2 - tickOpts.backdropPaddingY, 72057 labelWidth + tickOpts.backdropPaddingX * 2, 72058 tickFont.size + tickOpts.backdropPaddingY * 2 72059 ); 72060 } 72061 72062 ctx.textAlign = 'center'; 72063 ctx.textBaseline = 'middle'; 72064 ctx.fillStyle = tickFontColor; 72065 ctx.fillText(label, 0, -yCenterOffset); 72066 ctx.restore(); 72067 } 72068 } 72069 }); 72070 } 72071 } 72072}); 72073 72074// INTERNAL: static default options, registered in src/index.js 72075var _defaults$3 = defaultConfig$3; 72076scale_radialLinear._defaults = _defaults$3; 72077 72078var valueOrDefault$c = helpers$1.valueOrDefault; 72079 72080// Integer constants are from the ES6 spec. 72081var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991; 72082var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; 72083 72084var INTERVALS = { 72085 millisecond: { 72086 common: true, 72087 size: 1, 72088 steps: [1, 2, 5, 10, 20, 50, 100, 250, 500] 72089 },
vendor: 7,892 bytes, lines 72090-72386
72090 second: { 72091 common: true, 72092 size: 1000, 72093 steps: [1, 2, 5, 10, 15, 30] 72094 }, 72095 minute: { 72096 common: true, 72097 size: 60000, 72098 steps: [1, 2, 5, 10, 15, 30] 72099 }, 72100 hour: { 72101 common: true, 72102 size: 3600000, 72103 steps: [1, 2, 3, 6, 12] 72104 }, 72105 day: { 72106 common: true, 72107 size: 86400000, 72108 steps: [1, 2, 5] 72109 }, 72110 week: { 72111 common: false, 72112 size: 604800000, 72113 steps: [1, 2, 3, 4] 72114 }, 72115 month: { 72116 common: true, 72117 size: 2.628e9, 72118 steps: [1, 2, 3] 72119 }, 72120 quarter: { 72121 common: false, 72122 size: 7.884e9, 72123 steps: [1, 2, 3, 4] 72124 }, 72125 year: { 72126 common: true, 72127 size: 3.154e10 72128 } 72129}; 72130 72131var UNITS = Object.keys(INTERVALS); 72132 72133function sorter(a, b) { 72134 return a - b; 72135} 72136 72137function arrayUnique(items) { 72138 var hash = {}; 72139 var out = []; 72140 var i, ilen, item; 72141 72142 for (i = 0, ilen = items.length; i < ilen; ++i) { 72143 item = items[i]; 72144 if (!hash[item]) { 72145 hash[item] = true; 72146 out.push(item); 72147 } 72148 } 72149 72150 return out; 72151} 72152 72153/** 72154 * Returns an array of {time, pos} objects used to interpolate a specific `time` or position 72155 * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is 72156 * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other 72157 * extremity (left + width or top + height). Note that it would be more optimized to directly 72158 * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need 72159 * to create the lookup table. The table ALWAYS contains at least two items: min and max. 72160 * 72161 * @param {number[]} timestamps - timestamps sorted from lowest to highest. 72162 * @param {string} distribution - If 'linear', timestamps will be spread linearly along the min 72163 * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}. 72164 * If 'series', timestamps will be positioned at the same distance from each other. In this 72165 * case, only timestamps that break the time linearity are registered, meaning that in the 72166 * best case, all timestamps are linear, the table contains only min and max. 72167 */ 72168function buildLookupTable(timestamps, min, max, distribution) { 72169 if (distribution === 'linear' || !timestamps.length) { 72170 return [ 72171 {time: min, pos: 0}, 72172 {time: max, pos: 1} 72173 ]; 72174 } 72175 72176 var table = []; 72177 var items = [min]; 72178 var i, ilen, prev, curr, next; 72179 72180 for (i = 0, ilen = timestamps.length; i < ilen; ++i) { 72181 curr = timestamps[i]; 72182 if (curr > min && curr < max) { 72183 items.push(curr); 72184 } 72185 } 72186 72187 items.push(max); 72188 72189 for (i = 0, ilen = items.length; i < ilen; ++i) { 72190 next = items[i + 1]; 72191 prev = items[i - 1]; 72192 curr = items[i]; 72193 72194 // only add points that breaks the scale linearity 72195 if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) { 72196 table.push({time: curr, pos: i / (ilen - 1)}); 72197 } 72198 } 72199 72200 return table; 72201} 72202 72203// @see adapted from https://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/ 72204function lookup(table, key, value) { 72205 var lo = 0; 72206 var hi = table.length - 1; 72207 var mid, i0, i1; 72208 72209 while (lo >= 0 && lo <= hi) { 72210 mid = (lo + hi) >> 1; 72211 i0 = table[mid - 1] || null; 72212 i1 = table[mid]; 72213 72214 if (!i0) { 72215 // given value is outside table (before first item) 72216 return {lo: null, hi: i1}; 72217 } else if (i1[key] < value) { 72218 lo = mid + 1; 72219 } else if (i0[key] > value) { 72220 hi = mid - 1; 72221 } else { 72222 return {lo: i0, hi: i1}; 72223 } 72224 } 72225 72226 // given value is outside table (after last item) 72227 return {lo: i1, hi: null}; 72228} 72229 72230/** 72231 * Linearly interpolates the given source `value` using the table items `skey` values and 72232 * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos') 72233 * returns the position for a timestamp equal to 42. If value is out of bounds, values at 72234 * index [0, 1] or [n - 1, n] are used for the interpolation. 72235 */ 72236function interpolate$1(table, skey, sval, tkey) { 72237 var range = lookup(table, skey, sval); 72238 72239 // Note: the lookup table ALWAYS contains at least 2 items (min and max) 72240 var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo; 72241 var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi; 72242 72243 var span = next[skey] - prev[skey]; 72244 var ratio = span ? (sval - prev[skey]) / span : 0; 72245 var offset = (next[tkey] - prev[tkey]) * ratio; 72246 72247 return prev[tkey] + offset; 72248} 72249 72250function toTimestamp(scale, input) { 72251 var adapter = scale._adapter; 72252 var options = scale.options.time; 72253 var parser = options.parser; 72254 var format = parser || options.format; 72255 var value = input; 72256 72257 if (typeof parser === 'function') { 72258 value = parser(value); 72259 } 72260 72261 // Only parse if its not a timestamp already 72262 if (!helpers$1.isFinite(value)) { 72263 value = typeof format === 'string' 72264 ? adapter.parse(value, format) 72265 : adapter.parse(value); 72266 } 72267 72268 if (value !== null) { 72269 return +value; 72270 } 72271 72272 // Labels are in an incompatible format and no `parser` has been provided. 72273 // The user might still use the deprecated `format` option for parsing. 72274 if (!parser && typeof format === 'function') { 72275 value = format(input); 72276 72277 // `format` could return something else than a timestamp, if so, parse it 72278 if (!helpers$1.isFinite(value)) { 72279 value = adapter.parse(value); 72280 } 72281 } 72282 72283 return value; 72284} 72285 72286function parse(scale, input) { 72287 if (helpers$1.isNullOrUndef(input)) { 72288 return null; 72289 } 72290 72291 var options = scale.options.time; 72292 var value = toTimestamp(scale, scale.getRightValue(input)); 72293 if (value === null) { 72294 return value; 72295 } 72296 72297 if (options.round) { 72298 value = +scale._adapter.startOf(value, options.round); 72299 } 72300 72301 return value; 72302} 72303 72304/** 72305 * Returns the number of unit to skip to be able to display up to `capacity` number of ticks 72306 * in `unit` for the given `min` / `max` range and respecting the interval steps constraints. 72307 */ 72308function determineStepSize(min, max, unit, capacity) { 72309 var range = max - min; 72310 var interval = INTERVALS[unit]; 72311 var milliseconds = interval.size; 72312 var steps = interval.steps; 72313 var i, ilen, factor; 72314 72315 if (!steps) { 72316 return Math.ceil(range / (capacity * milliseconds)); 72317 } 72318 72319 for (i = 0, ilen = steps.length; i < ilen; ++i) { 72320 factor = steps[i]; 72321 if (Math.ceil(range / (milliseconds * factor)) <= capacity) { 72322 break; 72323 } 72324 } 72325 72326 return factor; 72327} 72328 72329/** 72330 * Figures out what unit results in an appropriate number of auto-generated ticks 72331 */ 72332function determineUnitForAutoTicks(minUnit, min, max, capacity) { 72333 var ilen = UNITS.length; 72334 var i, interval, factor; 72335 72336 for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) { 72337 interval = INTERVALS[UNITS[i]]; 72338 factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER; 72339 72340 if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) { 72341 return UNITS[i]; 72342 } 72343 } 72344 72345 return UNITS[ilen - 1]; 72346} 72347 72348/** 72349 * Figures out what unit to format a set of ticks with 72350 */ 72351function determineUnitForFormatting(scale, ticks, minUnit, min, max) { 72352 var ilen = UNITS.length; 72353 var i, unit; 72354 72355 for (i = ilen - 1; i >= UNITS.indexOf(minUnit); i--) { 72356 unit = UNITS[i]; 72357 if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= ticks.length) { 72358 return unit; 72359 } 72360 } 72361 72362 return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0]; 72363} 72364 72365function determineMajorUnit(unit) { 72366 for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) { 72367 if (INTERVALS[UNITS[i]].common) { 72368 return UNITS[i]; 72369 } 72370 } 72371} 72372 72373/** 72374 * Generates a maximum of `capacity` timestamps between min and max, rounded to the 72375 * `minor` unit, aligned on the `major` unit and using the given scale time `options`. 72376 * Important: this method can return ticks outside the min and max range, it's the 72377 * responsibility of the calling code to clamp values if needed. 72378 */ 72379function generate(scale, min, max, capacity) { 72380 var adapter = scale._adapter; 72381 var options = scale.options; 72382 var timeOpts = options.time; 72383 var minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, capacity); 72384 var major = determineMajorUnit(minor); 72385 var stepSize = valueOrDefault$c(timeOpts.stepSize, timeOpts.unitStepSize); 72386 var weekday = minor === 'week' ? timeOpts.isoWeekday : false;
72387 var majorTicksEnabled = options.ticks.major.enabled; 72388 var interval = INTERVALS[minor]; 72389 var first = min; 72390 var last = max; 72391 var ticks = []; 72392 var time; 72393 72394 if (!stepSize) { 72395 stepSize = determineStepSize(min, max, minor, capacity); 72396 } 72397 72398 // For 'week' unit, handle the first day of week option 72399 if (weekday) { 72400 first = +adapter.startOf(first, 'isoWeek', weekday); 72401 last = +adapter.startOf(last, 'isoWeek', weekday); 72402 } 72403 72404 // Align first/last ticks on unit 72405 first = +adapter.startOf(first, weekday ? 'day' : minor); 72406 last = +adapter.startOf(last, weekday ? 'day' : minor); 72407 72408 // Make sure that the last tick include max 72409 if (last < max) { 72410 last = +adapter.add(last, 1, minor); 72411 } 72412 72413 time = first; 72414 72415 if (majorTicksEnabled && major && !weekday && !timeOpts.round) { 72416 // Align the first tick on the previous `minor` unit aligned on the `major` unit: 72417 // we first aligned time on the previous `major` unit then add the number of full 72418 // stepSize there is between first and the previous major time. 72419 time = +adapter.startOf(time, major); 72420 time = +adapter.add(time, ~~((first - time) / (interval.size * stepSize)) * stepSize, minor); 72421 } 72422 72423 for (; time < last; time = +adapter.add(time, stepSize, minor)) { 72424 ticks.push(+time); 72425 } 72426 72427 ticks.push(+time); 72428 72429 return ticks; 72430} 72431 72432/** 72433 * Returns the start and end offsets from edges in the form of {start, end} 72434 * where each value is a relative width to the scale and ranges between 0 and 1. 72435 * They add extra margins on the both sides by scaling down the original scale. 72436 * Offsets are added when the `offset` option is true. 72437 */ 72438function computeOffsets(table, ticks, min, max, options) { 72439 var start = 0; 72440 var end = 0; 72441 var first, last; 72442 72443 if (options.offset && ticks.length) { 72444 if (!options.time.min) { 72445 first = interpolate$1(table, 'time', ticks[0], 'pos'); 72446 if (ticks.length === 1) { 72447 start = 1 - first; 72448 } else { 72449 start = (interpolate$1(table, 'time', ticks[1], 'pos') - first) / 2; 72450 } 72451 } 72452 if (!options.time.max) { 72453 last = interpolate$1(table, 'time', ticks[ticks.length - 1], 'pos'); 72454 if (ticks.length === 1) { 72455 end = last; 72456 } else { 72457 end = (last - interpolate$1(table, 'time', ticks[ticks.length - 2], 'pos')) / 2; 72458 } 72459 } 72460 } 72461 72462 return {start: start, end: end}; 72463} 72464 72465function ticksFromTimestamps(scale, values, majorUnit) { 72466 var ticks = []; 72467 var i, ilen, value, major; 72468 72469 for (i = 0, ilen = values.length; i < ilen; ++i) { 72470 value = values[i]; 72471 major = majorUnit ? value === +scale._adapter.startOf(value, majorUnit) : false; 72472 72473 ticks.push({ 72474 value: value, 72475 major: major 72476 }); 72477 } 72478 72479 return ticks; 72480} 72481 72482var defaultConfig$4 = { 72483 position: 'bottom', 72484 72485 /** 72486 * Data distribution along the scale: 72487 * - 'linear': data are spread according to their time (distances can vary), 72488 * - 'series': data are spread at the same distance from each other. 72489 * @see https://github.com/chartjs/Chart.js/pull/4507 72490 * @since 2.7.0 72491 */ 72492 distribution: 'linear', 72493 72494 /** 72495 * Scale boundary strategy (bypassed by min/max time options) 72496 * - `data`: make sure data are fully visible, ticks outside are removed 72497 * - `ticks`: make sure ticks are fully visible, data outside are truncated 72498 * @see https://github.com/chartjs/Chart.js/pull/4556 72499 * @since 2.7.0 72500 */ 72501 bounds: 'data', 72502 72503 adapters: {}, 72504 time: { 72505 parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment 72506 format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from https://momentjs.com/docs/#/parsing/string-format/ 72507 unit: false, // false == automatic or override with week, month, year, etc. 72508 round: false, // none, or override with week, month, year, etc. 72509 displayFormat: false, // DEPRECATED 72510 isoWeekday: false, // override week start day - see https://momentjs.com/docs/#/get-set/iso-weekday/ 72511 minUnit: 'millisecond', 72512 displayFormats: {} 72513 }, 72514 ticks: { 72515 autoSkip: false, 72516 72517 /** 72518 * Ticks generation input values: 72519 * - 'auto': generates "optimal" ticks based on scale size and time options. 72520 * - 'data': generates ticks from data (including labels from data {t|x|y} objects). 72521 * - 'labels': generates ticks from user given `data.labels` values ONLY. 72522 * @see https://github.com/chartjs/Chart.js/pull/4507 72523 * @since 2.7.0 72524 */ 72525 source: 'auto', 72526 72527 major: { 72528 enabled: false 72529 } 72530 } 72531}; 72532 72533var scale_time = core_scale.extend({ 72534 initialize: function() { 72535 this.mergeTicksOptions(); 72536 core_scale.prototype.initialize.call(this); 72537 }, 72538 72539 update: function() { 72540 var me = this; 72541 var options = me.options; 72542 var time = options.time || (options.time = {}); 72543 var adapter = me._adapter = new core_adapters._date(options.adapters.date); 72544 72545 // DEPRECATIONS: output a message only one time per update 72546 if (time.format) { 72547 console.warn('options.time.format is deprecated and replaced by options.time.parser.'); 72548 } 72549 72550 // Backward compatibility: before introducing adapter, `displayFormats` was 72551 // supposed to contain *all* unit/string pairs but this can't be resolved
vendor: 7,553 bytes, lines 72552-72814
72552 // when loading the scale (adapters are loaded afterward), so let's populate 72553 // missing formats on update 72554 helpers$1.mergeIf(time.displayFormats, adapter.formats()); 72555 72556 return core_scale.prototype.update.apply(me, arguments); 72557 }, 72558 72559 /** 72560 * Allows data to be referenced via 't' attribute 72561 */ 72562 getRightValue: function(rawValue) { 72563 if (rawValue && rawValue.t !== undefined) { 72564 rawValue = rawValue.t; 72565 } 72566 return core_scale.prototype.getRightValue.call(this, rawValue); 72567 }, 72568 72569 determineDataLimits: function() { 72570 var me = this; 72571 var chart = me.chart; 72572 var adapter = me._adapter; 72573 var timeOpts = me.options.time; 72574 var unit = timeOpts.unit || 'day'; 72575 var min = MAX_INTEGER; 72576 var max = MIN_INTEGER; 72577 var timestamps = []; 72578 var datasets = []; 72579 var labels = []; 72580 var i, j, ilen, jlen, data, timestamp; 72581 var dataLabels = chart.data.labels || []; 72582 72583 // Convert labels to timestamps 72584 for (i = 0, ilen = dataLabels.length; i < ilen; ++i) { 72585 labels.push(parse(me, dataLabels[i])); 72586 } 72587 72588 // Convert data to timestamps 72589 for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { 72590 if (chart.isDatasetVisible(i)) { 72591 data = chart.data.datasets[i].data; 72592 72593 // Let's consider that all data have the same format. 72594 if (helpers$1.isObject(data[0])) { 72595 datasets[i] = []; 72596 72597 for (j = 0, jlen = data.length; j < jlen; ++j) { 72598 timestamp = parse(me, data[j]); 72599 timestamps.push(timestamp); 72600 datasets[i][j] = timestamp; 72601 } 72602 } else { 72603 for (j = 0, jlen = labels.length; j < jlen; ++j) { 72604 timestamps.push(labels[j]); 72605 } 72606 datasets[i] = labels.slice(0); 72607 } 72608 } else { 72609 datasets[i] = []; 72610 } 72611 } 72612 72613 if (labels.length) { 72614 // Sort labels **after** data have been converted 72615 labels = arrayUnique(labels).sort(sorter); 72616 min = Math.min(min, labels[0]); 72617 max = Math.max(max, labels[labels.length - 1]); 72618 } 72619 72620 if (timestamps.length) { 72621 timestamps = arrayUnique(timestamps).sort(sorter); 72622 min = Math.min(min, timestamps[0]); 72623 max = Math.max(max, timestamps[timestamps.length - 1]); 72624 } 72625 72626 min = parse(me, timeOpts.min) || min; 72627 max = parse(me, timeOpts.max) || max; 72628 72629 // In case there is no valid min/max, set limits based on unit time option 72630 min = min === MAX_INTEGER ? +adapter.startOf(Date.now(), unit) : min; 72631 max = max === MIN_INTEGER ? +adapter.endOf(Date.now(), unit) + 1 : max; 72632 72633 // Make sure that max is strictly higher than min (required by the lookup table) 72634 me.min = Math.min(min, max); 72635 me.max = Math.max(min + 1, max); 72636 72637 // PRIVATE 72638 me._horizontal = me.isHorizontal(); 72639 me._table = []; 72640 me._timestamps = { 72641 data: timestamps, 72642 datasets: datasets, 72643 labels: labels 72644 }; 72645 }, 72646 72647 buildTicks: function() { 72648 var me = this; 72649 var min = me.min; 72650 var max = me.max; 72651 var options = me.options; 72652 var timeOpts = options.time; 72653 var timestamps = []; 72654 var ticks = []; 72655 var i, ilen, timestamp; 72656 72657 switch (options.ticks.source) { 72658 case 'data': 72659 timestamps = me._timestamps.data; 72660 break; 72661 case 'labels': 72662 timestamps = me._timestamps.labels; 72663 break; 72664 case 'auto': 72665 default: 72666 timestamps = generate(me, min, max, me.getLabelCapacity(min), options); 72667 } 72668 72669 if (options.bounds === 'ticks' && timestamps.length) { 72670 min = timestamps[0]; 72671 max = timestamps[timestamps.length - 1]; 72672 } 72673 72674 // Enforce limits with user min/max options 72675 min = parse(me, timeOpts.min) || min; 72676 max = parse(me, timeOpts.max) || max; 72677 72678 // Remove ticks outside the min/max range 72679 for (i = 0, ilen = timestamps.length; i < ilen; ++i) { 72680 timestamp = timestamps[i]; 72681 if (timestamp >= min && timestamp <= max) { 72682 ticks.push(timestamp); 72683 } 72684 } 72685 72686 me.min = min; 72687 me.max = max; 72688 72689 // PRIVATE 72690 me._unit = timeOpts.unit || determineUnitForFormatting(me, ticks, timeOpts.minUnit, me.min, me.max); 72691 me._majorUnit = determineMajorUnit(me._unit); 72692 me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution); 72693 me._offsets = computeOffsets(me._table, ticks, min, max, options); 72694 72695 if (options.ticks.reverse) { 72696 ticks.reverse(); 72697 } 72698 72699 return ticksFromTimestamps(me, ticks, me._majorUnit); 72700 }, 72701 72702 getLabelForIndex: function(index, datasetIndex) { 72703 var me = this; 72704 var adapter = me._adapter; 72705 var data = me.chart.data; 72706 var timeOpts = me.options.time; 72707 var label = data.labels && index < data.labels.length ? data.labels[index] : ''; 72708 var value = data.datasets[datasetIndex].data[index]; 72709 72710 if (helpers$1.isObject(value)) { 72711 label = me.getRightValue(value); 72712 } 72713 if (timeOpts.tooltipFormat) { 72714 return adapter.format(toTimestamp(me, label), timeOpts.tooltipFormat); 72715 } 72716 if (typeof label === 'string') { 72717 return label; 72718 } 72719 return adapter.format(toTimestamp(me, label), timeOpts.displayFormats.datetime); 72720 }, 72721 72722 /** 72723 * Function to format an individual tick mark 72724 * @private 72725 */ 72726 tickFormatFunction: function(time, index, ticks, format) { 72727 var me = this; 72728 var adapter = me._adapter; 72729 var options = me.options; 72730 var formats = options.time.displayFormats; 72731 var minorFormat = formats[me._unit]; 72732 var majorUnit = me._majorUnit; 72733 var majorFormat = formats[majorUnit]; 72734 var majorTime = +adapter.startOf(time, majorUnit); 72735 var majorTickOpts = options.ticks.major; 72736 var major = majorTickOpts.enabled && majorUnit && majorFormat && time === majorTime; 72737 var label = adapter.format(time, format ? format : major ? majorFormat : minorFormat); 72738 var tickOpts = major ? majorTickOpts : options.ticks.minor; 72739 var formatter = valueOrDefault$c(tickOpts.callback, tickOpts.userCallback); 72740 72741 return formatter ? formatter(label, index, ticks) : label; 72742 }, 72743 72744 convertTicksToLabels: function(ticks) { 72745 var labels = []; 72746 var i, ilen; 72747 72748 for (i = 0, ilen = ticks.length; i < ilen; ++i) { 72749 labels.push(this.tickFormatFunction(ticks[i].value, i, ticks)); 72750 } 72751 72752 return labels; 72753 }, 72754 72755 /** 72756 * @private 72757 */ 72758 getPixelForOffset: function(time) { 72759 var me = this; 72760 var isReverse = me.options.ticks.reverse; 72761 var size = me._horizontal ? me.width : me.height; 72762 var start = me._horizontal ? isReverse ? me.right : me.left : isReverse ? me.bottom : me.top; 72763 var pos = interpolate$1(me._table, 'time', time, 'pos'); 72764 var offset = size * (me._offsets.start + pos) / (me._offsets.start + 1 + me._offsets.end); 72765 72766 return isReverse ? start - offset : start + offset; 72767 }, 72768 72769 getPixelForValue: function(value, index, datasetIndex) { 72770 var me = this; 72771 var time = null; 72772 72773 if (index !== undefined && datasetIndex !== undefined) { 72774 time = me._timestamps.datasets[datasetIndex][index]; 72775 } 72776 72777 if (time === null) { 72778 time = parse(me, value); 72779 } 72780 72781 if (time !== null) { 72782 return me.getPixelForOffset(time); 72783 } 72784 }, 72785 72786 getPixelForTick: function(index) { 72787 var ticks = this.getTicks(); 72788 return index >= 0 && index < ticks.length ? 72789 this.getPixelForOffset(ticks[index].value) : 72790 null; 72791 }, 72792 72793 getValueForPixel: function(pixel) { 72794 var me = this; 72795 var size = me._horizontal ? me.width : me.height; 72796 var start = me._horizontal ? me.left : me.top; 72797 var pos = (size ? (pixel - start) / size : 0) * (me._offsets.start + 1 + me._offsets.start) - me._offsets.end; 72798 var time = interpolate$1(me._table, 'pos', pos, 'time'); 72799 72800 // DEPRECATION, we should return time directly 72801 return me._adapter._create(time); 72802 }, 72803 72804 /** 72805 * Crude approximation of what the label width might be 72806 * @private 72807 */ 72808 getLabelWidth: function(label) { 72809 var me = this; 72810 var ticksOpts = me.options.ticks; 72811 var tickLabelWidth = me.ctx.measureText(label).width; 72812 var angle = helpers$1.toRadians(ticksOpts.maxRotation); 72813 var cosRotation = Math.cos(angle); 72814 var sinRotation = Math.sin(angle);
vendor: 143,338 bytes, lines 72815-77216
72815 var tickFontSize = valueOrDefault$c(ticksOpts.fontSize, core_defaults.global.defaultFontSize); 72816 72817 return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); 72818 }, 72819 72820 /** 72821 * @private 72822 */ 72823 getLabelCapacity: function(exampleTime) { 72824 var me = this; 72825 72826 // pick the longest format (milliseconds) for guestimation 72827 var format = me.options.time.displayFormats.millisecond; 72828 var exampleLabel = me.tickFormatFunction(exampleTime, 0, [], format); 72829 var tickLabelWidth = me.getLabelWidth(exampleLabel); 72830 var innerWidth = me.isHorizontal() ? me.width : me.height; 72831 var capacity = Math.floor(innerWidth / tickLabelWidth); 72832 72833 return capacity > 0 ? capacity : 1; 72834 } 72835}); 72836 72837// INTERNAL: static default options, registered in src/index.js 72838var _defaults$4 = defaultConfig$4; 72839scale_time._defaults = _defaults$4; 72840 72841var scales = { 72842 category: scale_category, 72843 linear: scale_linear, 72844 logarithmic: scale_logarithmic, 72845 radialLinear: scale_radialLinear, 72846 time: scale_time 72847}; 72848 72849var moment = createCommonjsModule(function (module, exports) { 72850(function (global, factory) { 72851 module.exports = factory(); 72852}(commonjsGlobal, (function () { 72853 var hookCallback; 72854 72855 function hooks () { 72856 return hookCallback.apply(null, arguments); 72857 } 72858 72859 // This is done to register the method called with moment() 72860 // without creating circular dependencies. 72861 function setHookCallback (callback) { 72862 hookCallback = callback; 72863 } 72864 72865 function isArray(input) { 72866 return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; 72867 } 72868 72869 function isObject(input) { 72870 // IE8 will treat undefined and null as object if it wasn't for 72871 // input != null 72872 return input != null && Object.prototype.toString.call(input) === '[object Object]'; 72873 } 72874 72875 function isObjectEmpty(obj) { 72876 if (Object.getOwnPropertyNames) { 72877 return (Object.getOwnPropertyNames(obj).length === 0); 72878 } else { 72879 var k; 72880 for (k in obj) { 72881 if (obj.hasOwnProperty(k)) { 72882 return false; 72883 } 72884 } 72885 return true; 72886 } 72887 } 72888 72889 function isUndefined(input) { 72890 return input === void 0; 72891 } 72892 72893 function isNumber(input) { 72894 return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]'; 72895 } 72896 72897 function isDate(input) { 72898 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; 72899 } 72900 72901 function map(arr, fn) { 72902 var res = [], i; 72903 for (i = 0; i < arr.length; ++i) { 72904 res.push(fn(arr[i], i)); 72905 } 72906 return res; 72907 } 72908 72909 function hasOwnProp(a, b) { 72910 return Object.prototype.hasOwnProperty.call(a, b); 72911 } 72912 72913 function extend(a, b) { 72914 for (var i in b) { 72915 if (hasOwnProp(b, i)) { 72916 a[i] = b[i]; 72917 } 72918 } 72919 72920 if (hasOwnProp(b, 'toString')) { 72921 a.toString = b.toString; 72922 } 72923 72924 if (hasOwnProp(b, 'valueOf')) { 72925 a.valueOf = b.valueOf; 72926 } 72927 72928 return a; 72929 } 72930 72931 function createUTC (input, format, locale, strict) { 72932 return createLocalOrUTC(input, format, locale, strict, true).utc(); 72933 } 72934 72935 function defaultParsingFlags() { 72936 // We need to deep clone this object. 72937 return { 72938 empty : false, 72939 unusedTokens : [], 72940 unusedInput : [], 72941 overflow : -2, 72942 charsLeftOver : 0, 72943 nullInput : false, 72944 invalidMonth : null, 72945 invalidFormat : false, 72946 userInvalidated : false, 72947 iso : false, 72948 parsedDateParts : [], 72949 meridiem : null, 72950 rfc2822 : false, 72951 weekdayMismatch : false 72952 }; 72953 } 72954 72955 function getParsingFlags(m) { 72956 if (m._pf == null) { 72957 m._pf = defaultParsingFlags(); 72958 } 72959 return m._pf; 72960 } 72961 72962 var some; 72963 if (Array.prototype.some) { 72964 some = Array.prototype.some; 72965 } else { 72966 some = function (fun) { 72967 var t = Object(this); 72968 var len = t.length >>> 0; 72969 72970 for (var i = 0; i < len; i++) { 72971 if (i in t && fun.call(this, t[i], i, t)) { 72972 return true; 72973 } 72974 } 72975 72976 return false; 72977 }; 72978 } 72979 72980 function isValid(m) { 72981 if (m._isValid == null) { 72982 var flags = getParsingFlags(m); 72983 var parsedParts = some.call(flags.parsedDateParts, function (i) { 72984 return i != null; 72985 }); 72986 var isNowValid = !isNaN(m._d.getTime()) && 72987 flags.overflow < 0 && 72988 !flags.empty && 72989 !flags.invalidMonth && 72990 !flags.invalidWeekday && 72991 !flags.weekdayMismatch && 72992 !flags.nullInput && 72993 !flags.invalidFormat && 72994 !flags.userInvalidated && 72995 (!flags.meridiem || (flags.meridiem && parsedParts)); 72996 72997 if (m._strict) { 72998 isNowValid = isNowValid && 72999 flags.charsLeftOver === 0 && 73000 flags.unusedTokens.length === 0 && 73001 flags.bigHour === undefined; 73002 } 73003 73004 if (Object.isFrozen == null || !Object.isFrozen(m)) { 73005 m._isValid = isNowValid; 73006 } 73007 else { 73008 return isNowValid; 73009 } 73010 } 73011 return m._isValid; 73012 } 73013 73014 function createInvalid (flags) { 73015 var m = createUTC(NaN); 73016 if (flags != null) { 73017 extend(getParsingFlags(m), flags); 73018 } 73019 else { 73020 getParsingFlags(m).userInvalidated = true; 73021 } 73022 73023 return m; 73024 } 73025 73026 // Plugins that add properties should also add the key here (null value), 73027 // so we can properly clone ourselves. 73028 var momentProperties = hooks.momentProperties = []; 73029 73030 function copyConfig(to, from) { 73031 var i, prop, val; 73032 73033 if (!isUndefined(from._isAMomentObject)) { 73034 to._isAMomentObject = from._isAMomentObject; 73035 } 73036 if (!isUndefined(from._i)) { 73037 to._i = from._i; 73038 } 73039 if (!isUndefined(from._f)) { 73040 to._f = from._f; 73041 } 73042 if (!isUndefined(from._l)) { 73043 to._l = from._l; 73044 } 73045 if (!isUndefined(from._strict)) { 73046 to._strict = from._strict; 73047 } 73048 if (!isUndefined(from._tzm)) { 73049 to._tzm = from._tzm; 73050 } 73051 if (!isUndefined(from._isUTC)) { 73052 to._isUTC = from._isUTC; 73053 } 73054 if (!isUndefined(from._offset)) { 73055 to._offset = from._offset; 73056 } 73057 if (!isUndefined(from._pf)) { 73058 to._pf = getParsingFlags(from); 73059 } 73060 if (!isUndefined(from._locale)) { 73061 to._locale = from._locale; 73062 } 73063 73064 if (momentProperties.length > 0) { 73065 for (i = 0; i < momentProperties.length; i++) { 73066 prop = momentProperties[i]; 73067 val = from[prop]; 73068 if (!isUndefined(val)) { 73069 to[prop] = val; 73070 } 73071 } 73072 } 73073 73074 return to; 73075 } 73076 73077 var updateInProgress = false; 73078 73079 // Moment prototype object 73080 function Moment(config) { 73081 copyConfig(this, config); 73082 this._d = new Date(config._d != null ? config._d.getTime() : NaN); 73083 if (!this.isValid()) { 73084 this._d = new Date(NaN); 73085 } 73086 // Prevent infinite loop in case updateOffset creates new moment 73087 // objects. 73088 if (updateInProgress === false) { 73089 updateInProgress = true; 73090 hooks.updateOffset(this); 73091 updateInProgress = false; 73092 } 73093 } 73094 73095 function isMoment (obj) { 73096 return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); 73097 } 73098 73099 function absFloor (number) { 73100 if (number < 0) { 73101 // -0 -> 0 73102 return Math.ceil(number) || 0; 73103 } else { 73104 return Math.floor(number); 73105 } 73106 } 73107 73108 function toInt(argumentForCoercion) { 73109 var coercedNumber = +argumentForCoercion, 73110 value = 0; 73111 73112 if (coercedNumber !== 0 && isFinite(coercedNumber)) { 73113 value = absFloor(coercedNumber); 73114 } 73115 73116 return value; 73117 } 73118 73119 // compare two arrays, return the number of differences 73120 function compareArrays(array1, array2, dontConvert) { 73121 var len = Math.min(array1.length, array2.length), 73122 lengthDiff = Math.abs(array1.length - array2.length), 73123 diffs = 0, 73124 i; 73125 for (i = 0; i < len; i++) { 73126 if ((dontConvert && array1[i] !== array2[i]) || 73127 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { 73128 diffs++; 73129 } 73130 } 73131 return diffs + lengthDiff; 73132 } 73133 73134 function warn(msg) { 73135 if (hooks.suppressDeprecationWarnings === false && 73136 (typeof console !== 'undefined') && console.warn) { 73137 console.warn('Deprecation warning: ' + msg); 73138 } 73139 } 73140 73141 function deprecate(msg, fn) { 73142 var firstTime = true; 73143 73144 return extend(function () { 73145 if (hooks.deprecationHandler != null) { 73146 hooks.deprecationHandler(null, msg); 73147 } 73148 if (firstTime) { 73149 var args = []; 73150 var arg; 73151 for (var i = 0; i < arguments.length; i++) { 73152 arg = ''; 73153 if (typeof arguments[i] === 'object') { 73154 arg += '\n[' + i + '] '; 73155 for (var key in arguments[0]) { 73156 arg += key + ': ' + arguments[0][key] + ', '; 73157 } 73158 arg = arg.slice(0, -2); // Remove trailing comma and space 73159 } else { 73160 arg = arguments[i]; 73161 } 73162 args.push(arg); 73163 } 73164 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack); 73165 firstTime = false; 73166 } 73167 return fn.apply(this, arguments); 73168 }, fn); 73169 } 73170 73171 var deprecations = {}; 73172 73173 function deprecateSimple(name, msg) { 73174 if (hooks.deprecationHandler != null) { 73175 hooks.deprecationHandler(name, msg); 73176 } 73177 if (!deprecations[name]) { 73178 warn(msg); 73179 deprecations[name] = true; 73180 } 73181 } 73182 73183 hooks.suppressDeprecationWarnings = false; 73184 hooks.deprecationHandler = null; 73185 73186 function isFunction(input) { 73187 return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; 73188 } 73189 73190 function set (config) { 73191 var prop, i; 73192 for (i in config) { 73193 prop = config[i]; 73194 if (isFunction(prop)) { 73195 this[i] = prop; 73196 } else { 73197 this['_' + i] = prop; 73198 } 73199 } 73200 this._config = config; 73201 // Lenient ordinal parsing accepts just a number in addition to 73202 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse. 73203 // TODO: Remove "ordinalParse" fallback in next major release. 73204 this._dayOfMonthOrdinalParseLenient = new RegExp( 73205 (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + 73206 '|' + (/\d{1,2}/).source); 73207 } 73208 73209 function mergeConfigs(parentConfig, childConfig) { 73210 var res = extend({}, parentConfig), prop; 73211 for (prop in childConfig) { 73212 if (hasOwnProp(childConfig, prop)) { 73213 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { 73214 res[prop] = {}; 73215 extend(res[prop], parentConfig[prop]); 73216 extend(res[prop], childConfig[prop]); 73217 } else if (childConfig[prop] != null) { 73218 res[prop] = childConfig[prop]; 73219 } else { 73220 delete res[prop]; 73221 } 73222 } 73223 } 73224 for (prop in parentConfig) { 73225 if (hasOwnProp(parentConfig, prop) && 73226 !hasOwnProp(childConfig, prop) && 73227 isObject(parentConfig[prop])) { 73228 // make sure changes to properties don't modify parent config 73229 res[prop] = extend({}, res[prop]); 73230 } 73231 } 73232 return res; 73233 } 73234 73235 function Locale(config) { 73236 if (config != null) { 73237 this.set(config); 73238 } 73239 } 73240 73241 var keys; 73242 73243 if (Object.keys) { 73244 keys = Object.keys; 73245 } else { 73246 keys = function (obj) { 73247 var i, res = []; 73248 for (i in obj) { 73249 if (hasOwnProp(obj, i)) { 73250 res.push(i); 73251 } 73252 } 73253 return res; 73254 }; 73255 } 73256 73257 var defaultCalendar = { 73258 sameDay : '[Today at] LT', 73259 nextDay : '[Tomorrow at] LT', 73260 nextWeek : 'dddd [at] LT', 73261 lastDay : '[Yesterday at] LT', 73262 lastWeek : '[Last] dddd [at] LT', 73263 sameElse : 'L' 73264 }; 73265 73266 function calendar (key, mom, now) { 73267 var output = this._calendar[key] || this._calendar['sameElse']; 73268 return isFunction(output) ? output.call(mom, now) : output; 73269 } 73270 73271 var defaultLongDateFormat = { 73272 LTS : 'h:mm:ss A', 73273 LT : 'h:mm A', 73274 L : 'MM/DD/YYYY', 73275 LL : 'MMMM D, YYYY', 73276 LLL : 'MMMM D, YYYY h:mm A', 73277 LLLL : 'dddd, MMMM D, YYYY h:mm A' 73278 }; 73279 73280 function longDateFormat (key) { 73281 var format = this._longDateFormat[key], 73282 formatUpper = this._longDateFormat[key.toUpperCase()]; 73283 73284 if (format || !formatUpper) { 73285 return format; 73286 } 73287 73288 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { 73289 return val.slice(1); 73290 }); 73291 73292 return this._longDateFormat[key]; 73293 } 73294 73295 var defaultInvalidDate = 'Invalid date'; 73296 73297 function invalidDate () { 73298 return this._invalidDate; 73299 } 73300 73301 var defaultOrdinal = '%d'; 73302 var defaultDayOfMonthOrdinalParse = /\d{1,2}/; 73303 73304 function ordinal (number) { 73305 return this._ordinal.replace('%d', number); 73306 } 73307 73308 var defaultRelativeTime = { 73309 future : 'in %s', 73310 past : '%s ago', 73311 s : 'a few seconds', 73312 ss : '%d seconds', 73313 m : 'a minute', 73314 mm : '%d minutes', 73315 h : 'an hour', 73316 hh : '%d hours', 73317 d : 'a day', 73318 dd : '%d days', 73319 M : 'a month', 73320 MM : '%d months', 73321 y : 'a year', 73322 yy : '%d years' 73323 }; 73324 73325 function relativeTime (number, withoutSuffix, string, isFuture) { 73326 var output = this._relativeTime[string]; 73327 return (isFunction(output)) ? 73328 output(number, withoutSuffix, string, isFuture) : 73329 output.replace(/%d/i, number); 73330 } 73331 73332 function pastFuture (diff, output) { 73333 var format = this._relativeTime[diff > 0 ? 'future' : 'past']; 73334 return isFunction(format) ? format(output) : format.replace(/%s/i, output); 73335 } 73336 73337 var aliases = {}; 73338 73339 function addUnitAlias (unit, shorthand) { 73340 var lowerCase = unit.toLowerCase(); 73341 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; 73342 } 73343 73344 function normalizeUnits(units) { 73345 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; 73346 } 73347 73348 function normalizeObjectUnits(inputObject) { 73349 var normalizedInput = {}, 73350 normalizedProp, 73351 prop; 73352 73353 for (prop in inputObject) { 73354 if (hasOwnProp(inputObject, prop)) { 73355 normalizedProp = normalizeUnits(prop); 73356 if (normalizedProp) { 73357 normalizedInput[normalizedProp] = inputObject[prop]; 73358 } 73359 } 73360 } 73361 73362 return normalizedInput; 73363 } 73364 73365 var priorities = {}; 73366 73367 function addUnitPriority(unit, priority) { 73368 priorities[unit] = priority; 73369 } 73370 73371 function getPrioritizedUnits(unitsObj) { 73372 var units = []; 73373 for (var u in unitsObj) { 73374 units.push({unit: u, priority: priorities[u]}); 73375 } 73376 units.sort(function (a, b) { 73377 return a.priority - b.priority; 73378 }); 73379 return units; 73380 } 73381 73382 function zeroFill(number, targetLength, forceSign) { 73383 var absNumber = '' + Math.abs(number), 73384 zerosToFill = targetLength - absNumber.length, 73385 sign = number >= 0; 73386 return (sign ? (forceSign ? '+' : '') : '-') + 73387 Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; 73388 } 73389 73390 var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; 73391 73392 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; 73393 73394 var formatFunctions = {}; 73395 73396 var formatTokenFunctions = {}; 73397 73398 // token: 'M' 73399 // padded: ['MM', 2] 73400 // ordinal: 'Mo' 73401 // callback: function () { this.month() + 1 } 73402 function addFormatToken (token, padded, ordinal, callback) { 73403 var func = callback; 73404 if (typeof callback === 'string') { 73405 func = function () { 73406 return this[callback](); 73407 }; 73408 } 73409 if (token) { 73410 formatTokenFunctions[token] = func; 73411 } 73412 if (padded) { 73413 formatTokenFunctions[padded[0]] = function () { 73414 return zeroFill(func.apply(this, arguments), padded[1], padded[2]); 73415 }; 73416 } 73417 if (ordinal) { 73418 formatTokenFunctions[ordinal] = function () { 73419 return this.localeData().ordinal(func.apply(this, arguments), token); 73420 }; 73421 } 73422 } 73423 73424 function removeFormattingTokens(input) { 73425 if (input.match(/\[[\s\S]/)) { 73426 return input.replace(/^\[|\]$/g, ''); 73427 } 73428 return input.replace(/\\/g, ''); 73429 } 73430 73431 function makeFormatFunction(format) { 73432 var array = format.match(formattingTokens), i, length; 73433 73434 for (i = 0, length = array.length; i < length; i++) { 73435 if (formatTokenFunctions[array[i]]) { 73436 array[i] = formatTokenFunctions[array[i]]; 73437 } else { 73438 array[i] = removeFormattingTokens(array[i]); 73439 } 73440 } 73441 73442 return function (mom) { 73443 var output = '', i; 73444 for (i = 0; i < length; i++) { 73445 output += isFunction(array[i]) ? array[i].call(mom, format) : array[i]; 73446 } 73447 return output; 73448 }; 73449 } 73450 73451 // format date using native date object 73452 function formatMoment(m, format) { 73453 if (!m.isValid()) { 73454 return m.localeData().invalidDate(); 73455 } 73456 73457 format = expandFormat(format, m.localeData()); 73458 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); 73459 73460 return formatFunctions[format](m); 73461 } 73462 73463 function expandFormat(format, locale) { 73464 var i = 5; 73465 73466 function replaceLongDateFormatTokens(input) { 73467 return locale.longDateFormat(input) || input; 73468 } 73469 73470 localFormattingTokens.lastIndex = 0; 73471 while (i >= 0 && localFormattingTokens.test(format)) { 73472 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); 73473 localFormattingTokens.lastIndex = 0; 73474 i -= 1; 73475 } 73476 73477 return format; 73478 } 73479 73480 var match1 = /\d/; // 0 - 9 73481 var match2 = /\d\d/; // 00 - 99 73482 var match3 = /\d{3}/; // 000 - 999 73483 var match4 = /\d{4}/; // 0000 - 9999 73484 var match6 = /[+-]?\d{6}/; // -999999 - 999999 73485 var match1to2 = /\d\d?/; // 0 - 99 73486 var match3to4 = /\d\d\d\d?/; // 999 - 9999 73487 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 73488 var match1to3 = /\d{1,3}/; // 0 - 999 73489 var match1to4 = /\d{1,4}/; // 0 - 9999 73490 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 73491 73492 var matchUnsigned = /\d+/; // 0 - inf 73493 var matchSigned = /[+-]?\d+/; // -inf - inf 73494 73495 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z 73496 var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z 73497 73498 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 73499 73500 // any word (or two) characters or numbers including two/three word month in arabic. 73501 // includes scottish gaelic two word and hyphenated months 73502 var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i; 73503 73504 var regexes = {}; 73505 73506 function addRegexToken (token, regex, strictRegex) { 73507 regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { 73508 return (isStrict && strictRegex) ? strictRegex : regex; 73509 }; 73510 } 73511 73512 function getParseRegexForToken (token, config) { 73513 if (!hasOwnProp(regexes, token)) { 73514 return new RegExp(unescapeFormat(token)); 73515 } 73516 73517 return regexes[token](config._strict, config._locale); 73518 } 73519 73520 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript 73521 function unescapeFormat(s) { 73522 return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { 73523 return p1 || p2 || p3 || p4; 73524 })); 73525 } 73526 73527 function regexEscape(s) { 73528 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 73529 } 73530 73531 var tokens = {}; 73532 73533 function addParseToken (token, callback) { 73534 var i, func = callback; 73535 if (typeof token === 'string') { 73536 token = [token]; 73537 } 73538 if (isNumber(callback)) { 73539 func = function (input, array) { 73540 array[callback] = toInt(input); 73541 }; 73542 } 73543 for (i = 0; i < token.length; i++) { 73544 tokens[token[i]] = func; 73545 } 73546 } 73547 73548 function addWeekParseToken (token, callback) { 73549 addParseToken(token, function (input, array, config, token) { 73550 config._w = config._w || {}; 73551 callback(input, config._w, config, token); 73552 }); 73553 } 73554 73555 function addTimeToArrayFromToken(token, input, config) { 73556 if (input != null && hasOwnProp(tokens, token)) { 73557 tokens[token](input, config._a, config, token); 73558 } 73559 } 73560 73561 var YEAR = 0; 73562 var MONTH = 1; 73563 var DATE = 2; 73564 var HOUR = 3; 73565 var MINUTE = 4; 73566 var SECOND = 5; 73567 var MILLISECOND = 6; 73568 var WEEK = 7; 73569 var WEEKDAY = 8; 73570 73571 // FORMATTING 73572 73573 addFormatToken('Y', 0, 0, function () { 73574 var y = this.year(); 73575 return y <= 9999 ? '' + y : '+' + y; 73576 }); 73577 73578 addFormatToken(0, ['YY', 2], 0, function () { 73579 return this.year() % 100; 73580 }); 73581 73582 addFormatToken(0, ['YYYY', 4], 0, 'year'); 73583 addFormatToken(0, ['YYYYY', 5], 0, 'year'); 73584 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); 73585 73586 // ALIASES 73587 73588 addUnitAlias('year', 'y'); 73589 73590 // PRIORITIES 73591 73592 addUnitPriority('year', 1); 73593 73594 // PARSING 73595 73596 addRegexToken('Y', matchSigned); 73597 addRegexToken('YY', match1to2, match2); 73598 addRegexToken('YYYY', match1to4, match4); 73599 addRegexToken('YYYYY', match1to6, match6); 73600 addRegexToken('YYYYYY', match1to6, match6); 73601 73602 addParseToken(['YYYYY', 'YYYYYY'], YEAR); 73603 addParseToken('YYYY', function (input, array) { 73604 array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); 73605 }); 73606 addParseToken('YY', function (input, array) { 73607 array[YEAR] = hooks.parseTwoDigitYear(input); 73608 }); 73609 addParseToken('Y', function (input, array) { 73610 array[YEAR] = parseInt(input, 10); 73611 }); 73612 73613 // HELPERS 73614 73615 function daysInYear(year) { 73616 return isLeapYear(year) ? 366 : 365; 73617 } 73618 73619 function isLeapYear(year) { 73620 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; 73621 } 73622 73623 // HOOKS 73624 73625 hooks.parseTwoDigitYear = function (input) { 73626 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); 73627 }; 73628 73629 // MOMENTS 73630 73631 var getSetYear = makeGetSet('FullYear', true); 73632 73633 function getIsLeapYear () { 73634 return isLeapYear(this.year()); 73635 } 73636 73637 function makeGetSet (unit, keepTime) { 73638 return function (value) { 73639 if (value != null) { 73640 set$1(this, unit, value); 73641 hooks.updateOffset(this, keepTime); 73642 return this; 73643 } else { 73644 return get(this, unit); 73645 } 73646 }; 73647 } 73648 73649 function get (mom, unit) { 73650 return mom.isValid() ? 73651 mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; 73652 } 73653 73654 function set$1 (mom, unit, value) { 73655 if (mom.isValid() && !isNaN(value)) { 73656 if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) { 73657 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month())); 73658 } 73659 else { 73660 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); 73661 } 73662 } 73663 } 73664 73665 // MOMENTS 73666 73667 function stringGet (units) { 73668 units = normalizeUnits(units); 73669 if (isFunction(this[units])) { 73670 return this[units](); 73671 } 73672 return this; 73673 } 73674 73675 73676 function stringSet (units, value) { 73677 if (typeof units === 'object') { 73678 units = normalizeObjectUnits(units); 73679 var prioritized = getPrioritizedUnits(units); 73680 for (var i = 0; i < prioritized.length; i++) { 73681 this[prioritized[i].unit](units[prioritized[i].unit]); 73682 } 73683 } else { 73684 units = normalizeUnits(units); 73685 if (isFunction(this[units])) { 73686 return this[units](value); 73687 } 73688 } 73689 return this; 73690 } 73691 73692 function mod(n, x) { 73693 return ((n % x) + x) % x; 73694 } 73695 73696 var indexOf; 73697 73698 if (Array.prototype.indexOf) { 73699 indexOf = Array.prototype.indexOf; 73700 } else { 73701 indexOf = function (o) { 73702 // I know 73703 var i; 73704 for (i = 0; i < this.length; ++i) { 73705 if (this[i] === o) { 73706 return i; 73707 } 73708 } 73709 return -1; 73710 }; 73711 } 73712 73713 function daysInMonth(year, month) { 73714 if (isNaN(year) || isNaN(month)) { 73715 return NaN; 73716 } 73717 var modMonth = mod(month, 12); 73718 year += (month - modMonth) / 12; 73719 return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2); 73720 } 73721 73722 // FORMATTING 73723 73724 addFormatToken('M', ['MM', 2], 'Mo', function () { 73725 return this.month() + 1; 73726 }); 73727 73728 addFormatToken('MMM', 0, 0, function (format) { 73729 return this.localeData().monthsShort(this, format); 73730 }); 73731 73732 addFormatToken('MMMM', 0, 0, function (format) { 73733 return this.localeData().months(this, format); 73734 }); 73735 73736 // ALIASES 73737 73738 addUnitAlias('month', 'M'); 73739 73740 // PRIORITY 73741 73742 addUnitPriority('month', 8); 73743 73744 // PARSING 73745 73746 addRegexToken('M', match1to2); 73747 addRegexToken('MM', match1to2, match2); 73748 addRegexToken('MMM', function (isStrict, locale) { 73749 return locale.monthsShortRegex(isStrict); 73750 }); 73751 addRegexToken('MMMM', function (isStrict, locale) { 73752 return locale.monthsRegex(isStrict); 73753 }); 73754 73755 addParseToken(['M', 'MM'], function (input, array) { 73756 array[MONTH] = toInt(input) - 1; 73757 }); 73758 73759 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { 73760 var month = config._locale.monthsParse(input, token, config._strict); 73761 // if we didn't find a month name, mark the date as invalid. 73762 if (month != null) { 73763 array[MONTH] = month; 73764 } else { 73765 getParsingFlags(config).invalidMonth = input; 73766 } 73767 }); 73768 73769 // LOCALES 73770 73771 var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/; 73772 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); 73773 function localeMonths (m, format) { 73774 if (!m) { 73775 return isArray(this._months) ? this._months : 73776 this._months['standalone']; 73777 } 73778 return isArray(this._months) ? this._months[m.month()] : 73779 this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; 73780 } 73781 73782 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); 73783 function localeMonthsShort (m, format) { 73784 if (!m) { 73785 return isArray(this._monthsShort) ? this._monthsShort : 73786 this._monthsShort['standalone']; 73787 } 73788 return isArray(this._monthsShort) ? this._monthsShort[m.month()] : 73789 this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; 73790 } 73791 73792 function handleStrictParse(monthName, format, strict) { 73793 var i, ii, mom, llc = monthName.toLocaleLowerCase(); 73794 if (!this._monthsParse) { 73795 // this is not used 73796 this._monthsParse = []; 73797 this._longMonthsParse = []; 73798 this._shortMonthsParse = []; 73799 for (i = 0; i < 12; ++i) { 73800 mom = createUTC([2000, i]); 73801 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); 73802 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); 73803 } 73804 } 73805 73806 if (strict) { 73807 if (format === 'MMM') { 73808 ii = indexOf.call(this._shortMonthsParse, llc); 73809 return ii !== -1 ? ii : null; 73810 } else { 73811 ii = indexOf.call(this._longMonthsParse, llc); 73812 return ii !== -1 ? ii : null; 73813 } 73814 } else { 73815 if (format === 'MMM') { 73816 ii = indexOf.call(this._shortMonthsParse, llc); 73817 if (ii !== -1) { 73818 return ii; 73819 } 73820 ii = indexOf.call(this._longMonthsParse, llc); 73821 return ii !== -1 ? ii : null; 73822 } else { 73823 ii = indexOf.call(this._longMonthsParse, llc); 73824 if (ii !== -1) { 73825 return ii; 73826 } 73827 ii = indexOf.call(this._shortMonthsParse, llc); 73828 return ii !== -1 ? ii : null; 73829 } 73830 } 73831 } 73832 73833 function localeMonthsParse (monthName, format, strict) { 73834 var i, mom, regex; 73835 73836 if (this._monthsParseExact) { 73837 return handleStrictParse.call(this, monthName, format, strict); 73838 } 73839 73840 if (!this._monthsParse) { 73841 this._monthsParse = []; 73842 this._longMonthsParse = []; 73843 this._shortMonthsParse = []; 73844 } 73845 73846 // TODO: add sorting 73847 // Sorting makes sure if one month (or abbr) is a prefix of another 73848 // see sorting in computeMonthsParse 73849 for (i = 0; i < 12; i++) { 73850 // make the regex if we don't have it already 73851 mom = createUTC([2000, i]); 73852 if (strict && !this._longMonthsParse[i]) { 73853 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); 73854 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); 73855 } 73856 if (!strict && !this._monthsParse[i]) { 73857 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); 73858 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); 73859 } 73860 // test the regex 73861 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { 73862 return i; 73863 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { 73864 return i; 73865 } else if (!strict && this._monthsParse[i].test(monthName)) { 73866 return i; 73867 } 73868 } 73869 } 73870 73871 // MOMENTS 73872 73873 function setMonth (mom, value) { 73874 var dayOfMonth; 73875 73876 if (!mom.isValid()) { 73877 // No op 73878 return mom; 73879 } 73880 73881 if (typeof value === 'string') { 73882 if (/^\d+$/.test(value)) { 73883 value = toInt(value); 73884 } else { 73885 value = mom.localeData().monthsParse(value); 73886 // TODO: Another silent failure? 73887 if (!isNumber(value)) { 73888 return mom; 73889 } 73890 } 73891 } 73892 73893 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); 73894 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); 73895 return mom; 73896 } 73897 73898 function getSetMonth (value) { 73899 if (value != null) { 73900 setMonth(this, value); 73901 hooks.updateOffset(this, true); 73902 return this; 73903 } else { 73904 return get(this, 'Month'); 73905 } 73906 } 73907 73908 function getDaysInMonth () { 73909 return daysInMonth(this.year(), this.month()); 73910 } 73911 73912 var defaultMonthsShortRegex = matchWord; 73913 function monthsShortRegex (isStrict) { 73914 if (this._monthsParseExact) { 73915 if (!hasOwnProp(this, '_monthsRegex')) { 73916 computeMonthsParse.call(this); 73917 } 73918 if (isStrict) { 73919 return this._monthsShortStrictRegex; 73920 } else { 73921 return this._monthsShortRegex; 73922 } 73923 } else { 73924 if (!hasOwnProp(this, '_monthsShortRegex')) { 73925 this._monthsShortRegex = defaultMonthsShortRegex; 73926 } 73927 return this._monthsShortStrictRegex && isStrict ? 73928 this._monthsShortStrictRegex : this._monthsShortRegex; 73929 } 73930 } 73931 73932 var defaultMonthsRegex = matchWord; 73933 function monthsRegex (isStrict) { 73934 if (this._monthsParseExact) { 73935 if (!hasOwnProp(this, '_monthsRegex')) { 73936 computeMonthsParse.call(this); 73937 } 73938 if (isStrict) { 73939 return this._monthsStrictRegex; 73940 } else { 73941 return this._monthsRegex; 73942 } 73943 } else { 73944 if (!hasOwnProp(this, '_monthsRegex')) { 73945 this._monthsRegex = defaultMonthsRegex; 73946 } 73947 return this._monthsStrictRegex && isStrict ? 73948 this._monthsStrictRegex : this._monthsRegex; 73949 } 73950 } 73951 73952 function computeMonthsParse () { 73953 function cmpLenRev(a, b) { 73954 return b.length - a.length; 73955 } 73956 73957 var shortPieces = [], longPieces = [], mixedPieces = [], 73958 i, mom; 73959 for (i = 0; i < 12; i++) { 73960 // make the regex if we don't have it already 73961 mom = createUTC([2000, i]); 73962 shortPieces.push(this.monthsShort(mom, '')); 73963 longPieces.push(this.months(mom, '')); 73964 mixedPieces.push(this.months(mom, '')); 73965 mixedPieces.push(this.monthsShort(mom, '')); 73966 } 73967 // Sorting makes sure if one month (or abbr) is a prefix of another it 73968 // will match the longer piece. 73969 shortPieces.sort(cmpLenRev); 73970 longPieces.sort(cmpLenRev); 73971 mixedPieces.sort(cmpLenRev); 73972 for (i = 0; i < 12; i++) { 73973 shortPieces[i] = regexEscape(shortPieces[i]); 73974 longPieces[i] = regexEscape(longPieces[i]); 73975 } 73976 for (i = 0; i < 24; i++) { 73977 mixedPieces[i] = regexEscape(mixedPieces[i]); 73978 } 73979 73980 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); 73981 this._monthsShortRegex = this._monthsRegex; 73982 this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); 73983 this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); 73984 } 73985 73986 function createDate (y, m, d, h, M, s, ms) { 73987 // can't just apply() to create a date: 73988 // https://stackoverflow.com/q/181348 73989 var date; 73990 // the date constructor remaps years 0-99 to 1900-1999 73991 if (y < 100 && y >= 0) { 73992 // preserve leap years using a full 400 year cycle, then reset 73993 date = new Date(y + 400, m, d, h, M, s, ms); 73994 if (isFinite(date.getFullYear())) { 73995 date.setFullYear(y); 73996 } 73997 } else { 73998 date = new Date(y, m, d, h, M, s, ms); 73999 } 74000 74001 return date; 74002 } 74003 74004 function createUTCDate (y) { 74005 var date; 74006 // the Date.UTC function remaps years 0-99 to 1900-1999 74007 if (y < 100 && y >= 0) { 74008 var args = Array.prototype.slice.call(arguments); 74009 // preserve leap years using a full 400 year cycle, then reset 74010 args[0] = y + 400; 74011 date = new Date(Date.UTC.apply(null, args)); 74012 if (isFinite(date.getUTCFullYear())) { 74013 date.setUTCFullYear(y); 74014 } 74015 } else { 74016 date = new Date(Date.UTC.apply(null, arguments)); 74017 } 74018 74019 return date; 74020 } 74021 74022 // start-of-first-week - start-of-year 74023 function firstWeekOffset(year, dow, doy) { 74024 var // first-week day -- which january is always in the first week (4 for iso, 1 for other) 74025 fwd = 7 + dow - doy, 74026 // first-week day local weekday -- which local weekday is fwd 74027 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; 74028 74029 return -fwdlw + fwd - 1; 74030 } 74031 74032 // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday 74033 function dayOfYearFromWeeks(year, week, weekday, dow, doy) { 74034 var localWeekday = (7 + weekday - dow) % 7, 74035 weekOffset = firstWeekOffset(year, dow, doy), 74036 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, 74037 resYear, resDayOfYear; 74038 74039 if (dayOfYear <= 0) { 74040 resYear = year - 1; 74041 resDayOfYear = daysInYear(resYear) + dayOfYear; 74042 } else if (dayOfYear > daysInYear(year)) { 74043 resYear = year + 1; 74044 resDayOfYear = dayOfYear - daysInYear(year); 74045 } else { 74046 resYear = year; 74047 resDayOfYear = dayOfYear; 74048 } 74049 74050 return { 74051 year: resYear, 74052 dayOfYear: resDayOfYear 74053 }; 74054 } 74055 74056 function weekOfYear(mom, dow, doy) { 74057 var weekOffset = firstWeekOffset(mom.year(), dow, doy), 74058 week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, 74059 resWeek, resYear; 74060 74061 if (week < 1) { 74062 resYear = mom.year() - 1; 74063 resWeek = week + weeksInYear(resYear, dow, doy); 74064 } else if (week > weeksInYear(mom.year(), dow, doy)) { 74065 resWeek = week - weeksInYear(mom.year(), dow, doy); 74066 resYear = mom.year() + 1; 74067 } else { 74068 resYear = mom.year(); 74069 resWeek = week; 74070 } 74071 74072 return { 74073 week: resWeek, 74074 year: resYear 74075 }; 74076 } 74077 74078 function weeksInYear(year, dow, doy) { 74079 var weekOffset = firstWeekOffset(year, dow, doy), 74080 weekOffsetNext = firstWeekOffset(year + 1, dow, doy); 74081 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; 74082 } 74083 74084 // FORMATTING 74085 74086 addFormatToken('w', ['ww', 2], 'wo', 'week'); 74087 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); 74088 74089 // ALIASES 74090 74091 addUnitAlias('week', 'w'); 74092 addUnitAlias('isoWeek', 'W'); 74093 74094 // PRIORITIES 74095 74096 addUnitPriority('week', 5); 74097 addUnitPriority('isoWeek', 5); 74098 74099 // PARSING 74100 74101 addRegexToken('w', match1to2); 74102 addRegexToken('ww', match1to2, match2); 74103 addRegexToken('W', match1to2); 74104 addRegexToken('WW', match1to2, match2); 74105 74106 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { 74107 week[token.substr(0, 1)] = toInt(input); 74108 }); 74109 74110 // HELPERS 74111 74112 // LOCALES 74113 74114 function localeWeek (mom) { 74115 return weekOfYear(mom, this._week.dow, this._week.doy).week; 74116 } 74117 74118 var defaultLocaleWeek = { 74119 dow : 0, // Sunday is the first day of the week. 74120 doy : 6 // The week that contains Jan 6th is the first week of the year. 74121 }; 74122 74123 function localeFirstDayOfWeek () { 74124 return this._week.dow; 74125 } 74126 74127 function localeFirstDayOfYear () { 74128 return this._week.doy; 74129 } 74130 74131 // MOMENTS 74132 74133 function getSetWeek (input) { 74134 var week = this.localeData().week(this); 74135 return input == null ? week : this.add((input - week) * 7, 'd'); 74136 } 74137 74138 function getSetISOWeek (input) { 74139 var week = weekOfYear(this, 1, 4).week; 74140 return input == null ? week : this.add((input - week) * 7, 'd'); 74141 } 74142 74143 // FORMATTING 74144 74145 addFormatToken('d', 0, 'do', 'day'); 74146 74147 addFormatToken('dd', 0, 0, function (format) { 74148 return this.localeData().weekdaysMin(this, format); 74149 }); 74150 74151 addFormatToken('ddd', 0, 0, function (format) { 74152 return this.localeData().weekdaysShort(this, format); 74153 }); 74154 74155 addFormatToken('dddd', 0, 0, function (format) { 74156 return this.localeData().weekdays(this, format); 74157 }); 74158 74159 addFormatToken('e', 0, 0, 'weekday'); 74160 addFormatToken('E', 0, 0, 'isoWeekday'); 74161 74162 // ALIASES 74163 74164 addUnitAlias('day', 'd'); 74165 addUnitAlias('weekday', 'e'); 74166 addUnitAlias('isoWeekday', 'E'); 74167 74168 // PRIORITY 74169 addUnitPriority('day', 11); 74170 addUnitPriority('weekday', 11); 74171 addUnitPriority('isoWeekday', 11); 74172 74173 // PARSING 74174 74175 addRegexToken('d', match1to2); 74176 addRegexToken('e', match1to2); 74177 addRegexToken('E', match1to2); 74178 addRegexToken('dd', function (isStrict, locale) { 74179 return locale.weekdaysMinRegex(isStrict); 74180 }); 74181 addRegexToken('ddd', function (isStrict, locale) { 74182 return locale.weekdaysShortRegex(isStrict); 74183 }); 74184 addRegexToken('dddd', function (isStrict, locale) { 74185 return locale.weekdaysRegex(isStrict); 74186 }); 74187 74188 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { 74189 var weekday = config._locale.weekdaysParse(input, token, config._strict); 74190 // if we didn't get a weekday name, mark the date as invalid 74191 if (weekday != null) { 74192 week.d = weekday; 74193 } else { 74194 getParsingFlags(config).invalidWeekday = input; 74195 } 74196 }); 74197 74198 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { 74199 week[token] = toInt(input); 74200 }); 74201 74202 // HELPERS 74203 74204 function parseWeekday(input, locale) { 74205 if (typeof input !== 'string') { 74206 return input; 74207 } 74208 74209 if (!isNaN(input)) { 74210 return parseInt(input, 10); 74211 } 74212 74213 input = locale.weekdaysParse(input); 74214 if (typeof input === 'number') { 74215 return input; 74216 } 74217 74218 return null; 74219 } 74220 74221 function parseIsoWeekday(input, locale) { 74222 if (typeof input === 'string') { 74223 return locale.weekdaysParse(input) % 7 || 7; 74224 } 74225 return isNaN(input) ? null : input; 74226 } 74227 74228 // LOCALES 74229 function shiftWeekdays (ws, n) { 74230 return ws.slice(n, 7).concat(ws.slice(0, n)); 74231 } 74232 74233 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); 74234 function localeWeekdays (m, format) { 74235 var weekdays = isArray(this._weekdays) ? this._weekdays : 74236 this._weekdays[(m && m !== true && this._weekdays.isFormat.test(format)) ? 'format' : 'standalone']; 74237 return (m === true) ? shiftWeekdays(weekdays, this._week.dow) 74238 : (m) ? weekdays[m.day()] : weekdays; 74239 } 74240 74241 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); 74242 function localeWeekdaysShort (m) { 74243 return (m === true) ? shiftWeekdays(this._weekdaysShort, this._week.dow) 74244 : (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort; 74245 } 74246 74247 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); 74248 function localeWeekdaysMin (m) { 74249 return (m === true) ? shiftWeekdays(this._weekdaysMin, this._week.dow) 74250 : (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin; 74251 } 74252 74253 function handleStrictParse$1(weekdayName, format, strict) { 74254 var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); 74255 if (!this._weekdaysParse) { 74256 this._weekdaysParse = []; 74257 this._shortWeekdaysParse = []; 74258 this._minWeekdaysParse = []; 74259 74260 for (i = 0; i < 7; ++i) { 74261 mom = createUTC([2000, 1]).day(i); 74262 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); 74263 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); 74264 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); 74265 } 74266 } 74267 74268 if (strict) { 74269 if (format === 'dddd') { 74270 ii = indexOf.call(this._weekdaysParse, llc); 74271 return ii !== -1 ? ii : null; 74272 } else if (format === 'ddd') { 74273 ii = indexOf.call(this._shortWeekdaysParse, llc); 74274 return ii !== -1 ? ii : null; 74275 } else { 74276 ii = indexOf.call(this._minWeekdaysParse, llc); 74277 return ii !== -1 ? ii : null; 74278 } 74279 } else { 74280 if (format === 'dddd') { 74281 ii = indexOf.call(this._weekdaysParse, llc); 74282 if (ii !== -1) { 74283 return ii; 74284 } 74285 ii = indexOf.call(this._shortWeekdaysParse, llc); 74286 if (ii !== -1) { 74287 return ii; 74288 } 74289 ii = indexOf.call(this._minWeekdaysParse, llc); 74290 return ii !== -1 ? ii : null; 74291 } else if (format === 'ddd') { 74292 ii = indexOf.call(this._shortWeekdaysParse, llc); 74293 if (ii !== -1) { 74294 return ii; 74295 } 74296 ii = indexOf.call(this._weekdaysParse, llc); 74297 if (ii !== -1) { 74298 return ii; 74299 } 74300 ii = indexOf.call(this._minWeekdaysParse, llc); 74301 return ii !== -1 ? ii : null; 74302 } else { 74303 ii = indexOf.call(this._minWeekdaysParse, llc); 74304 if (ii !== -1) { 74305 return ii; 74306 } 74307 ii = indexOf.call(this._weekdaysParse, llc); 74308 if (ii !== -1) { 74309 return ii; 74310 } 74311 ii = indexOf.call(this._shortWeekdaysParse, llc); 74312 return ii !== -1 ? ii : null; 74313 } 74314 } 74315 } 74316 74317 function localeWeekdaysParse (weekdayName, format, strict) { 74318 var i, mom, regex; 74319 74320 if (this._weekdaysParseExact) { 74321 return handleStrictParse$1.call(this, weekdayName, format, strict); 74322 } 74323 74324 if (!this._weekdaysParse) { 74325 this._weekdaysParse = []; 74326 this._minWeekdaysParse = []; 74327 this._shortWeekdaysParse = []; 74328 this._fullWeekdaysParse = []; 74329 } 74330 74331 for (i = 0; i < 7; i++) { 74332 // make the regex if we don't have it already 74333 74334 mom = createUTC([2000, 1]).day(i); 74335 if (strict && !this._fullWeekdaysParse[i]) { 74336 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i'); 74337 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i'); 74338 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i'); 74339 } 74340 if (!this._weekdaysParse[i]) { 74341 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); 74342 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); 74343 } 74344 // test the regex 74345 if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { 74346 return i; 74347 } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { 74348 return i; 74349 } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { 74350 return i; 74351 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { 74352 return i; 74353 } 74354 } 74355 } 74356 74357 // MOMENTS 74358 74359 function getSetDayOfWeek (input) { 74360 if (!this.isValid()) { 74361 return input != null ? this : NaN; 74362 } 74363 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); 74364 if (input != null) { 74365 input = parseWeekday(input, this.localeData()); 74366 return this.add(input - day, 'd'); 74367 } else { 74368 return day; 74369 } 74370 } 74371 74372 function getSetLocaleDayOfWeek (input) { 74373 if (!this.isValid()) { 74374 return input != null ? this : NaN; 74375 } 74376 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; 74377 return input == null ? weekday : this.add(input - weekday, 'd'); 74378 } 74379 74380 function getSetISODayOfWeek (input) { 74381 if (!this.isValid()) { 74382 return input != null ? this : NaN; 74383 } 74384 74385 // behaves the same as moment#day except 74386 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) 74387 // as a setter, sunday should belong to the previous week. 74388 74389 if (input != null) { 74390 var weekday = parseIsoWeekday(input, this.localeData()); 74391 return this.day(this.day() % 7 ? weekday : weekday - 7); 74392 } else { 74393 return this.day() || 7; 74394 } 74395 } 74396 74397 var defaultWeekdaysRegex = matchWord; 74398 function weekdaysRegex (isStrict) { 74399 if (this._weekdaysParseExact) { 74400 if (!hasOwnProp(this, '_weekdaysRegex')) { 74401 computeWeekdaysParse.call(this); 74402 } 74403 if (isStrict) { 74404 return this._weekdaysStrictRegex; 74405 } else { 74406 return this._weekdaysRegex; 74407 } 74408 } else { 74409 if (!hasOwnProp(this, '_weekdaysRegex')) { 74410 this._weekdaysRegex = defaultWeekdaysRegex; 74411 } 74412 return this._weekdaysStrictRegex && isStrict ? 74413 this._weekdaysStrictRegex : this._weekdaysRegex; 74414 } 74415 } 74416 74417 var defaultWeekdaysShortRegex = matchWord; 74418 function weekdaysShortRegex (isStrict) { 74419 if (this._weekdaysParseExact) { 74420 if (!hasOwnProp(this, '_weekdaysRegex')) { 74421 computeWeekdaysParse.call(this); 74422 } 74423 if (isStrict) { 74424 return this._weekdaysShortStrictRegex; 74425 } else { 74426 return this._weekdaysShortRegex; 74427 } 74428 } else { 74429 if (!hasOwnProp(this, '_weekdaysShortRegex')) { 74430 this._weekdaysShortRegex = defaultWeekdaysShortRegex; 74431 } 74432 return this._weekdaysShortStrictRegex && isStrict ? 74433 this._weekdaysShortStrictRegex : this._weekdaysShortRegex; 74434 } 74435 } 74436 74437 var defaultWeekdaysMinRegex = matchWord; 74438 function weekdaysMinRegex (isStrict) { 74439 if (this._weekdaysParseExact) { 74440 if (!hasOwnProp(this, '_weekdaysRegex')) { 74441 computeWeekdaysParse.call(this); 74442 } 74443 if (isStrict) { 74444 return this._weekdaysMinStrictRegex; 74445 } else { 74446 return this._weekdaysMinRegex; 74447 } 74448 } else { 74449 if (!hasOwnProp(this, '_weekdaysMinRegex')) { 74450 this._weekdaysMinRegex = defaultWeekdaysMinRegex; 74451 } 74452 return this._weekdaysMinStrictRegex && isStrict ? 74453 this._weekdaysMinStrictRegex : this._weekdaysMinRegex; 74454 } 74455 } 74456 74457 74458 function computeWeekdaysParse () { 74459 function cmpLenRev(a, b) { 74460 return b.length - a.length; 74461 } 74462 74463 var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], 74464 i, mom, minp, shortp, longp; 74465 for (i = 0; i < 7; i++) { 74466 // make the regex if we don't have it already 74467 mom = createUTC([2000, 1]).day(i); 74468 minp = this.weekdaysMin(mom, ''); 74469 shortp = this.weekdaysShort(mom, ''); 74470 longp = this.weekdays(mom, ''); 74471 minPieces.push(minp); 74472 shortPieces.push(shortp); 74473 longPieces.push(longp); 74474 mixedPieces.push(minp); 74475 mixedPieces.push(shortp); 74476 mixedPieces.push(longp); 74477 } 74478 // Sorting makes sure if one weekday (or abbr) is a prefix of another it 74479 // will match the longer piece. 74480 minPieces.sort(cmpLenRev); 74481 shortPieces.sort(cmpLenRev); 74482 longPieces.sort(cmpLenRev); 74483 mixedPieces.sort(cmpLenRev); 74484 for (i = 0; i < 7; i++) { 74485 shortPieces[i] = regexEscape(shortPieces[i]); 74486 longPieces[i] = regexEscape(longPieces[i]); 74487 mixedPieces[i] = regexEscape(mixedPieces[i]); 74488 } 74489 74490 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); 74491 this._weekdaysShortRegex = this._weekdaysRegex; 74492 this._weekdaysMinRegex = this._weekdaysRegex; 74493 74494 this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); 74495 this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); 74496 this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); 74497 } 74498 74499 // FORMATTING 74500 74501 function hFormat() { 74502 return this.hours() % 12 || 12; 74503 } 74504 74505 function kFormat() { 74506 return this.hours() || 24; 74507 } 74508 74509 addFormatToken('H', ['HH', 2], 0, 'hour'); 74510 addFormatToken('h', ['hh', 2], 0, hFormat); 74511 addFormatToken('k', ['kk', 2], 0, kFormat); 74512 74513 addFormatToken('hmm', 0, 0, function () { 74514 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); 74515 }); 74516 74517 addFormatToken('hmmss', 0, 0, function () { 74518 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + 74519 zeroFill(this.seconds(), 2); 74520 }); 74521 74522 addFormatToken('Hmm', 0, 0, function () { 74523 return '' + this.hours() + zeroFill(this.minutes(), 2); 74524 }); 74525 74526 addFormatToken('Hmmss', 0, 0, function () { 74527 return '' + this.hours() + zeroFill(this.minutes(), 2) + 74528 zeroFill(this.seconds(), 2); 74529 }); 74530 74531 function meridiem (token, lowercase) { 74532 addFormatToken(token, 0, 0, function () { 74533 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); 74534 }); 74535 } 74536 74537 meridiem('a', true); 74538 meridiem('A', false); 74539 74540 // ALIASES 74541 74542 addUnitAlias('hour', 'h'); 74543 74544 // PRIORITY 74545 addUnitPriority('hour', 13); 74546 74547 // PARSING 74548 74549 function matchMeridiem (isStrict, locale) { 74550 return locale._meridiemParse; 74551 } 74552 74553 addRegexToken('a', matchMeridiem); 74554 addRegexToken('A', matchMeridiem); 74555 addRegexToken('H', match1to2); 74556 addRegexToken('h', match1to2); 74557 addRegexToken('k', match1to2); 74558 addRegexToken('HH', match1to2, match2); 74559 addRegexToken('hh', match1to2, match2); 74560 addRegexToken('kk', match1to2, match2); 74561 74562 addRegexToken('hmm', match3to4); 74563 addRegexToken('hmmss', match5to6); 74564 addRegexToken('Hmm', match3to4); 74565 addRegexToken('Hmmss', match5to6); 74566 74567 addParseToken(['H', 'HH'], HOUR); 74568 addParseToken(['k', 'kk'], function (input, array, config) { 74569 var kInput = toInt(input); 74570 array[HOUR] = kInput === 24 ? 0 : kInput; 74571 }); 74572 addParseToken(['a', 'A'], function (input, array, config) { 74573 config._isPm = config._locale.isPM(input); 74574 config._meridiem = input; 74575 }); 74576 addParseToken(['h', 'hh'], function (input, array, config) { 74577 array[HOUR] = toInt(input); 74578 getParsingFlags(config).bigHour = true; 74579 }); 74580 addParseToken('hmm', function (input, array, config) { 74581 var pos = input.length - 2; 74582 array[HOUR] = toInt(input.substr(0, pos)); 74583 array[MINUTE] = toInt(input.substr(pos)); 74584 getParsingFlags(config).bigHour = true; 74585 }); 74586 addParseToken('hmmss', function (input, array, config) { 74587 var pos1 = input.length - 4; 74588 var pos2 = input.length - 2; 74589 array[HOUR] = toInt(input.substr(0, pos1)); 74590 array[MINUTE] = toInt(input.substr(pos1, 2)); 74591 array[SECOND] = toInt(input.substr(pos2)); 74592 getParsingFlags(config).bigHour = true; 74593 }); 74594 addParseToken('Hmm', function (input, array, config) { 74595 var pos = input.length - 2; 74596 array[HOUR] = toInt(input.substr(0, pos)); 74597 array[MINUTE] = toInt(input.substr(pos)); 74598 }); 74599 addParseToken('Hmmss', function (input, array, config) { 74600 var pos1 = input.length - 4; 74601 var pos2 = input.length - 2; 74602 array[HOUR] = toInt(input.substr(0, pos1)); 74603 array[MINUTE] = toInt(input.substr(pos1, 2)); 74604 array[SECOND] = toInt(input.substr(pos2)); 74605 }); 74606 74607 // LOCALES 74608 74609 function localeIsPM (input) { 74610 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays 74611 // Using charAt should be more compatible. 74612 return ((input + '').toLowerCase().charAt(0) === 'p'); 74613 } 74614 74615 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; 74616 function localeMeridiem (hours, minutes, isLower) { 74617 if (hours > 11) { 74618 return isLower ? 'pm' : 'PM'; 74619 } else { 74620 return isLower ? 'am' : 'AM'; 74621 } 74622 } 74623 74624 74625 // MOMENTS 74626 74627 // Setting the hour should keep the time, because the user explicitly 74628 // specified which hour they want. So trying to maintain the same hour (in 74629 // a new timezone) makes sense. Adding/subtracting hours does not follow 74630 // this rule. 74631 var getSetHour = makeGetSet('Hours', true); 74632 74633 var baseConfig = { 74634 calendar: defaultCalendar, 74635 longDateFormat: defaultLongDateFormat, 74636 invalidDate: defaultInvalidDate, 74637 ordinal: defaultOrdinal, 74638 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, 74639 relativeTime: defaultRelativeTime, 74640 74641 months: defaultLocaleMonths, 74642 monthsShort: defaultLocaleMonthsShort, 74643 74644 week: defaultLocaleWeek, 74645 74646 weekdays: defaultLocaleWeekdays, 74647 weekdaysMin: defaultLocaleWeekdaysMin, 74648 weekdaysShort: defaultLocaleWeekdaysShort, 74649 74650 meridiemParse: defaultLocaleMeridiemParse 74651 }; 74652 74653 // internal storage for locale config files 74654 var locales = {}; 74655 var localeFamilies = {}; 74656 var globalLocale; 74657 74658 function normalizeLocale(key) { 74659 return key ? key.toLowerCase().replace('_', '-') : key; 74660 } 74661 74662 // pick the locale from the array 74663 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each 74664 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root 74665 function chooseLocale(names) { 74666 var i = 0, j, next, locale, split; 74667 74668 while (i < names.length) { 74669 split = normalizeLocale(names[i]).split('-'); 74670 j = split.length; 74671 next = normalizeLocale(names[i + 1]); 74672 next = next ? next.split('-') : null; 74673 while (j > 0) { 74674 locale = loadLocale(split.slice(0, j).join('-')); 74675 if (locale) { 74676 return locale; 74677 } 74678 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { 74679 //the next array item is better than a shallower substring of this one 74680 break; 74681 } 74682 j--; 74683 } 74684 i++; 74685 } 74686 return globalLocale; 74687 } 74688 74689 function loadLocale(name) { 74690 var oldLocale = null; 74691 // TODO: Find a better way to register and load all the locales in Node 74692 if (!locales[name] && ('object' !== 'undefined') && 74693 module && module.exports) { 74694 try { 74695 oldLocale = globalLocale._abbr; 74696 var aliasedRequire = commonjsRequire; 74697 aliasedRequire('./locale/' + name); 74698 getSetGlobalLocale(oldLocale); 74699 } catch (e) {} 74700 } 74701 return locales[name]; 74702 } 74703 74704 // This function will load locale and then set the global locale. If 74705 // no arguments are passed in, it will simply return the current global 74706 // locale key. 74707 function getSetGlobalLocale (key, values) { 74708 var data; 74709 if (key) { 74710 if (isUndefined(values)) { 74711 data = getLocale(key); 74712 } 74713 else { 74714 data = defineLocale(key, values); 74715 } 74716 74717 if (data) { 74718 // moment.duration._locale = moment._locale = data; 74719 globalLocale = data; 74720 } 74721 else { 74722 if ((typeof console !== 'undefined') && console.warn) { 74723 //warn user if arguments are passed but the locale could not be set 74724 console.warn('Locale ' + key + ' not found. Did you forget to load it?'); 74725 } 74726 } 74727 } 74728 74729 return globalLocale._abbr; 74730 } 74731 74732 function defineLocale (name, config) { 74733 if (config !== null) { 74734 var locale, parentConfig = baseConfig; 74735 config.abbr = name; 74736 if (locales[name] != null) { 74737 deprecateSimple('defineLocaleOverride', 74738 'use moment.updateLocale(localeName, config) to change ' + 74739 'an existing locale. moment.defineLocale(localeName, ' + 74740 'config) should only be used for creating a new locale ' + 74741 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); 74742 parentConfig = locales[name]._config; 74743 } else if (config.parentLocale != null) { 74744 if (locales[config.parentLocale] != null) { 74745 parentConfig = locales[config.parentLocale]._config; 74746 } else { 74747 locale = loadLocale(config.parentLocale); 74748 if (locale != null) { 74749 parentConfig = locale._config; 74750 } else { 74751 if (!localeFamilies[config.parentLocale]) { 74752 localeFamilies[config.parentLocale] = []; 74753 } 74754 localeFamilies[config.parentLocale].push({ 74755 name: name, 74756 config: config 74757 }); 74758 return null; 74759 } 74760 } 74761 } 74762 locales[name] = new Locale(mergeConfigs(parentConfig, config)); 74763 74764 if (localeFamilies[name]) { 74765 localeFamilies[name].forEach(function (x) { 74766 defineLocale(x.name, x.config); 74767 }); 74768 } 74769 74770 // backwards compat for now: also set the locale 74771 // make sure we set the locale AFTER all child locales have been 74772 // created, so we won't end up with the child locale set. 74773 getSetGlobalLocale(name); 74774 74775 74776 return locales[name]; 74777 } else { 74778 // useful for testing 74779 delete locales[name]; 74780 return null; 74781 } 74782 } 74783 74784 function updateLocale(name, config) { 74785 if (config != null) { 74786 var locale, tmpLocale, parentConfig = baseConfig; 74787 // MERGE 74788 tmpLocale = loadLocale(name); 74789 if (tmpLocale != null) { 74790 parentConfig = tmpLocale._config; 74791 } 74792 config = mergeConfigs(parentConfig, config); 74793 locale = new Locale(config); 74794 locale.parentLocale = locales[name]; 74795 locales[name] = locale; 74796 74797 // backwards compat for now: also set the locale 74798 getSetGlobalLocale(name); 74799 } else { 74800 // pass null for config to unupdate, useful for tests 74801 if (locales[name] != null) { 74802 if (locales[name].parentLocale != null) { 74803 locales[name] = locales[name].parentLocale; 74804 } else if (locales[name] != null) { 74805 delete locales[name]; 74806 } 74807 } 74808 } 74809 return locales[name]; 74810 } 74811 74812 // returns locale data 74813 function getLocale (key) { 74814 var locale; 74815 74816 if (key && key._locale && key._locale._abbr) { 74817 key = key._locale._abbr; 74818 } 74819 74820 if (!key) { 74821 return globalLocale; 74822 } 74823 74824 if (!isArray(key)) { 74825 //short-circuit everything else 74826 locale = loadLocale(key); 74827 if (locale) { 74828 return locale; 74829 } 74830 key = [key]; 74831 } 74832 74833 return chooseLocale(key); 74834 } 74835 74836 function listLocales() { 74837 return keys(locales); 74838 } 74839 74840 function checkOverflow (m) { 74841 var overflow; 74842 var a = m._a; 74843 74844 if (a && getParsingFlags(m).overflow === -2) { 74845 overflow = 74846 a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : 74847 a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : 74848 a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : 74849 a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : 74850 a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : 74851 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : 74852 -1; 74853 74854 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { 74855 overflow = DATE; 74856 } 74857 if (getParsingFlags(m)._overflowWeeks && overflow === -1) { 74858 overflow = WEEK; 74859 } 74860 if (getParsingFlags(m)._overflowWeekday && overflow === -1) { 74861 overflow = WEEKDAY; 74862 } 74863 74864 getParsingFlags(m).overflow = overflow; 74865 } 74866 74867 return m; 74868 } 74869 74870 // Pick the first defined of two or three arguments. 74871 function defaults(a, b, c) { 74872 if (a != null) { 74873 return a; 74874 } 74875 if (b != null) { 74876 return b; 74877 } 74878 return c; 74879 } 74880 74881 function currentDateArray(config) { 74882 // hooks is actually the exported moment object 74883 var nowValue = new Date(hooks.now()); 74884 if (config._useUTC) { 74885 return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; 74886 } 74887 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; 74888 } 74889 74890 // convert an array to a date. 74891 // the array should mirror the parameters below 74892 // note: all values past the year are optional and will default to the lowest possible value. 74893 // [year, month, day , hour, minute, second, millisecond] 74894 function configFromArray (config) { 74895 var i, date, input = [], currentDate, expectedWeekday, yearToUse; 74896 74897 if (config._d) { 74898 return; 74899 } 74900 74901 currentDate = currentDateArray(config); 74902 74903 //compute day of the year from weeks and weekdays 74904 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { 74905 dayOfYearFromWeekInfo(config); 74906 } 74907 74908 //if the day of the year is set, figure out what it is 74909 if (config._dayOfYear != null) { 74910 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); 74911 74912 if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) { 74913 getParsingFlags(config)._overflowDayOfYear = true; 74914 } 74915 74916 date = createUTCDate(yearToUse, 0, config._dayOfYear); 74917 config._a[MONTH] = date.getUTCMonth(); 74918 config._a[DATE] = date.getUTCDate(); 74919 } 74920 74921 // Default to current date. 74922 // * if no year, month, day of month are given, default to today 74923 // * if day of month is given, default month and year 74924 // * if month is given, default only year 74925 // * if year is given, don't default anything 74926 for (i = 0; i < 3 && config._a[i] == null; ++i) { 74927 config._a[i] = input[i] = currentDate[i]; 74928 } 74929 74930 // Zero out whatever was not defaulted, including time 74931 for (; i < 7; i++) { 74932 config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; 74933 } 74934 74935 // Check for 24:00:00.000 74936 if (config._a[HOUR] === 24 && 74937 config._a[MINUTE] === 0 && 74938 config._a[SECOND] === 0 && 74939 config._a[MILLISECOND] === 0) { 74940 config._nextDay = true; 74941 config._a[HOUR] = 0; 74942 } 74943 74944 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); 74945 expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); 74946 74947 // Apply timezone offset from input. The actual utcOffset can be changed 74948 // with parseZone. 74949 if (config._tzm != null) { 74950 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); 74951 } 74952 74953 if (config._nextDay) { 74954 config._a[HOUR] = 24; 74955 } 74956 74957 // check for mismatching day of week 74958 if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) { 74959 getParsingFlags(config).weekdayMismatch = true; 74960 } 74961 } 74962 74963 function dayOfYearFromWeekInfo(config) { 74964 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; 74965 74966 w = config._w; 74967 if (w.GG != null || w.W != null || w.E != null) { 74968 dow = 1; 74969 doy = 4; 74970 74971 // TODO: We need to take the current isoWeekYear, but that depends on 74972 // how we interpret now (local, utc, fixed offset). So create 74973 // a now version of current config (take local/utc/offset flags, and 74974 // create now). 74975 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); 74976 week = defaults(w.W, 1); 74977 weekday = defaults(w.E, 1); 74978 if (weekday < 1 || weekday > 7) { 74979 weekdayOverflow = true; 74980 } 74981 } else { 74982 dow = config._locale._week.dow; 74983 doy = config._locale._week.doy; 74984 74985 var curWeek = weekOfYear(createLocal(), dow, doy); 74986 74987 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); 74988 74989 // Default to current week. 74990 week = defaults(w.w, curWeek.week); 74991 74992 if (w.d != null) { 74993 // weekday -- low day numbers are considered next week 74994 weekday = w.d; 74995 if (weekday < 0 || weekday > 6) { 74996 weekdayOverflow = true; 74997 } 74998 } else if (w.e != null) { 74999 // local weekday -- counting starts from beginning of week 75000 weekday = w.e + dow; 75001 if (w.e < 0 || w.e > 6) { 75002 weekdayOverflow = true; 75003 } 75004 } else { 75005 // default to beginning of week 75006 weekday = dow; 75007 } 75008 } 75009 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { 75010 getParsingFlags(config)._overflowWeeks = true; 75011 } else if (weekdayOverflow != null) { 75012 getParsingFlags(config)._overflowWeekday = true; 75013 } else { 75014 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); 75015 config._a[YEAR] = temp.year; 75016 config._dayOfYear = temp.dayOfYear; 75017 } 75018 } 75019 75020 // iso 8601 regex 75021 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) 75022 var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; 75023 var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; 75024 75025 var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; 75026 75027 var isoDates = [ 75028 ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], 75029 ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], 75030 ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], 75031 ['GGGG-[W]WW', /\d{4}-W\d\d/, false], 75032 ['YYYY-DDD', /\d{4}-\d{3}/], 75033 ['YYYY-MM', /\d{4}-\d\d/, false], 75034 ['YYYYYYMMDD', /[+-]\d{10}/], 75035 ['YYYYMMDD', /\d{8}/], 75036 // YYYYMM is NOT allowed by the standard 75037 ['GGGG[W]WWE', /\d{4}W\d{3}/], 75038 ['GGGG[W]WW', /\d{4}W\d{2}/, false], 75039 ['YYYYDDD', /\d{7}/] 75040 ]; 75041 75042 // iso time formats and regexes 75043 var isoTimes = [ 75044 ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], 75045 ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], 75046 ['HH:mm:ss', /\d\d:\d\d:\d\d/], 75047 ['HH:mm', /\d\d:\d\d/], 75048 ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], 75049 ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], 75050 ['HHmmss', /\d\d\d\d\d\d/], 75051 ['HHmm', /\d\d\d\d/], 75052 ['HH', /\d\d/] 75053 ]; 75054 75055 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; 75056 75057 // date from iso format 75058 function configFromISO(config) { 75059 var i, l, 75060 string = config._i, 75061 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), 75062 allowTime, dateFormat, timeFormat, tzFormat; 75063 75064 if (match) { 75065 getParsingFlags(config).iso = true; 75066 75067 for (i = 0, l = isoDates.length; i < l; i++) { 75068 if (isoDates[i][1].exec(match[1])) { 75069 dateFormat = isoDates[i][0]; 75070 allowTime = isoDates[i][2] !== false; 75071 break; 75072 } 75073 } 75074 if (dateFormat == null) { 75075 config._isValid = false; 75076 return; 75077 } 75078 if (match[3]) { 75079 for (i = 0, l = isoTimes.length; i < l; i++) { 75080 if (isoTimes[i][1].exec(match[3])) { 75081 // match[2] should be 'T' or space 75082 timeFormat = (match[2] || ' ') + isoTimes[i][0]; 75083 break; 75084 } 75085 } 75086 if (timeFormat == null) { 75087 config._isValid = false; 75088 return; 75089 } 75090 } 75091 if (!allowTime && timeFormat != null) { 75092 config._isValid = false; 75093 return; 75094 } 75095 if (match[4]) { 75096 if (tzRegex.exec(match[4])) { 75097 tzFormat = 'Z'; 75098 } else { 75099 config._isValid = false; 75100 return; 75101 } 75102 } 75103 config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); 75104 configFromStringAndFormat(config); 75105 } else { 75106 config._isValid = false; 75107 } 75108 } 75109 75110 // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 75111 var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; 75112 75113 function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { 75114 var result = [ 75115 untruncateYear(yearStr), 75116 defaultLocaleMonthsShort.indexOf(monthStr), 75117 parseInt(dayStr, 10), 75118 parseInt(hourStr, 10), 75119 parseInt(minuteStr, 10) 75120 ]; 75121 75122 if (secondStr) { 75123 result.push(parseInt(secondStr, 10)); 75124 } 75125 75126 return result; 75127 } 75128 75129 function untruncateYear(yearStr) { 75130 var year = parseInt(yearStr, 10); 75131 if (year <= 49) { 75132 return 2000 + year; 75133 } else if (year <= 999) { 75134 return 1900 + year; 75135 } 75136 return year; 75137 } 75138 75139 function preprocessRFC2822(s) { 75140 // Remove comments and folding whitespace and replace multiple-spaces with a single space 75141 return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 75142 } 75143 75144 function checkWeekday(weekdayStr, parsedInput, config) { 75145 if (weekdayStr) { 75146 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. 75147 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), 75148 weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay(); 75149 if (weekdayProvided !== weekdayActual) { 75150 getParsingFlags(config).weekdayMismatch = true; 75151 config._isValid = false; 75152 return false; 75153 } 75154 } 75155 return true; 75156 } 75157 75158 var obsOffsets = { 75159 UT: 0, 75160 GMT: 0, 75161 EDT: -4 * 60, 75162 EST: -5 * 60, 75163 CDT: -5 * 60, 75164 CST: -6 * 60, 75165 MDT: -6 * 60, 75166 MST: -7 * 60, 75167 PDT: -7 * 60, 75168 PST: -8 * 60 75169 }; 75170 75171 function calculateOffset(obsOffset, militaryOffset, numOffset) { 75172 if (obsOffset) { 75173 return obsOffsets[obsOffset]; 75174 } else if (militaryOffset) { 75175 // the only allowed military tz is Z 75176 return 0; 75177 } else { 75178 var hm = parseInt(numOffset, 10); 75179 var m = hm % 100, h = (hm - m) / 100; 75180 return h * 60 + m; 75181 } 75182 } 75183 75184 // date and time from ref 2822 format 75185 function configFromRFC2822(config) { 75186 var match = rfc2822.exec(preprocessRFC2822(config._i)); 75187 if (match) { 75188 var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]); 75189 if (!checkWeekday(match[1], parsedArray, config)) { 75190 return; 75191 } 75192 75193 config._a = parsedArray; 75194 config._tzm = calculateOffset(match[8], match[9], match[10]); 75195 75196 config._d = createUTCDate.apply(null, config._a); 75197 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); 75198 75199 getParsingFlags(config).rfc2822 = true; 75200 } else { 75201 config._isValid = false; 75202 } 75203 } 75204 75205 // date from iso format or fallback 75206 function configFromString(config) { 75207 var matched = aspNetJsonRegex.exec(config._i); 75208 75209 if (matched !== null) { 75210 config._d = new Date(+matched[1]); 75211 return; 75212 } 75213 75214 configFromISO(config); 75215 if (config._isValid === false) { 75216 delete config._isValid; 75217 } else { 75218 return; 75219 } 75220 75221 configFromRFC2822(config); 75222 if (config._isValid === false) { 75223 delete config._isValid; 75224 } else { 75225 return; 75226 } 75227 75228 // Final attempt, use Input Fallback 75229 hooks.createFromInputFallback(config); 75230 } 75231 75232 hooks.createFromInputFallback = deprecate( 75233 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 75234 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 75235 'discouraged and will be removed in an upcoming major release. Please refer to ' + 75236 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', 75237 function (config) { 75238 config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); 75239 } 75240 ); 75241 75242 // constant that refers to the ISO standard 75243 hooks.ISO_8601 = function () {}; 75244 75245 // constant that refers to the RFC 2822 form 75246 hooks.RFC_2822 = function () {}; 75247 75248 // date from string and format string 75249 function configFromStringAndFormat(config) { 75250 // TODO: Move this to another part of the creation flow to prevent circular deps 75251 if (config._f === hooks.ISO_8601) { 75252 configFromISO(config); 75253 return; 75254 } 75255 if (config._f === hooks.RFC_2822) { 75256 configFromRFC2822(config); 75257 return; 75258 } 75259 config._a = []; 75260 getParsingFlags(config).empty = true; 75261 75262 // This array is used to make a Date, either with `new Date` or `Date.UTC` 75263 var string = '' + config._i, 75264 i, parsedInput, tokens, token, skipped, 75265 stringLength = string.length, 75266 totalParsedInputLength = 0; 75267 75268 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; 75269 75270 for (i = 0; i < tokens.length; i++) { 75271 token = tokens[i]; 75272 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; 75273 // console.log('token', token, 'parsedInput', parsedInput, 75274 // 'regex', getParseRegexForToken(token, config)); 75275 if (parsedInput) { 75276 skipped = string.substr(0, string.indexOf(parsedInput)); 75277 if (skipped.length > 0) { 75278 getParsingFlags(config).unusedInput.push(skipped); 75279 } 75280 string = string.slice(string.indexOf(parsedInput) + parsedInput.length); 75281 totalParsedInputLength += parsedInput.length; 75282 } 75283 // don't parse if it's not a known token 75284 if (formatTokenFunctions[token]) { 75285 if (parsedInput) { 75286 getParsingFlags(config).empty = false; 75287 } 75288 else { 75289 getParsingFlags(config).unusedTokens.push(token); 75290 } 75291 addTimeToArrayFromToken(token, parsedInput, config); 75292 } 75293 else if (config._strict && !parsedInput) { 75294 getParsingFlags(config).unusedTokens.push(token); 75295 } 75296 } 75297 75298 // add remaining unparsed input length to the string 75299 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; 75300 if (string.length > 0) { 75301 getParsingFlags(config).unusedInput.push(string); 75302 } 75303 75304 // clear _12h flag if hour is <= 12 75305 if (config._a[HOUR] <= 12 && 75306 getParsingFlags(config).bigHour === true && 75307 config._a[HOUR] > 0) { 75308 getParsingFlags(config).bigHour = undefined; 75309 } 75310 75311 getParsingFlags(config).parsedDateParts = config._a.slice(0); 75312 getParsingFlags(config).meridiem = config._meridiem; 75313 // handle meridiem 75314 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); 75315 75316 configFromArray(config); 75317 checkOverflow(config); 75318 } 75319 75320 75321 function meridiemFixWrap (locale, hour, meridiem) { 75322 var isPm; 75323 75324 if (meridiem == null) { 75325 // nothing to do 75326 return hour; 75327 } 75328 if (locale.meridiemHour != null) { 75329 return locale.meridiemHour(hour, meridiem); 75330 } else if (locale.isPM != null) { 75331 // Fallback 75332 isPm = locale.isPM(meridiem); 75333 if (isPm && hour < 12) { 75334 hour += 12; 75335 } 75336 if (!isPm && hour === 12) { 75337 hour = 0; 75338 } 75339 return hour; 75340 } else { 75341 // this is not supposed to happen 75342 return hour; 75343 } 75344 } 75345 75346 // date from string and array of format strings 75347 function configFromStringAndArray(config) { 75348 var tempConfig, 75349 bestMoment, 75350 75351 scoreToBeat, 75352 i, 75353 currentScore; 75354 75355 if (config._f.length === 0) { 75356 getParsingFlags(config).invalidFormat = true; 75357 config._d = new Date(NaN); 75358 return; 75359 } 75360 75361 for (i = 0; i < config._f.length; i++) { 75362 currentScore = 0; 75363 tempConfig = copyConfig({}, config); 75364 if (config._useUTC != null) { 75365 tempConfig._useUTC = config._useUTC; 75366 } 75367 tempConfig._f = config._f[i]; 75368 configFromStringAndFormat(tempConfig); 75369 75370 if (!isValid(tempConfig)) { 75371 continue; 75372 } 75373 75374 // if there is any input that was not parsed add a penalty for that format 75375 currentScore += getParsingFlags(tempConfig).charsLeftOver; 75376 75377 //or tokens 75378 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; 75379 75380 getParsingFlags(tempConfig).score = currentScore; 75381 75382 if (scoreToBeat == null || currentScore < scoreToBeat) { 75383 scoreToBeat = currentScore; 75384 bestMoment = tempConfig; 75385 } 75386 } 75387 75388 extend(config, bestMoment || tempConfig); 75389 } 75390 75391 function configFromObject(config) { 75392 if (config._d) { 75393 return; 75394 } 75395 75396 var i = normalizeObjectUnits(config._i); 75397 config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { 75398 return obj && parseInt(obj, 10); 75399 }); 75400 75401 configFromArray(config); 75402 } 75403 75404 function createFromConfig (config) { 75405 var res = new Moment(checkOverflow(prepareConfig(config))); 75406 if (res._nextDay) { 75407 // Adding is smart enough around DST 75408 res.add(1, 'd'); 75409 res._nextDay = undefined; 75410 } 75411 75412 return res; 75413 } 75414 75415 function prepareConfig (config) { 75416 var input = config._i, 75417 format = config._f; 75418 75419 config._locale = config._locale || getLocale(config._l); 75420 75421 if (input === null || (format === undefined && input === '')) { 75422 return createInvalid({nullInput: true}); 75423 } 75424 75425 if (typeof input === 'string') { 75426 config._i = input = config._locale.preparse(input); 75427 } 75428 75429 if (isMoment(input)) { 75430 return new Moment(checkOverflow(input)); 75431 } else if (isDate(input)) { 75432 config._d = input; 75433 } else if (isArray(format)) { 75434 configFromStringAndArray(config); 75435 } else if (format) { 75436 configFromStringAndFormat(config); 75437 } else { 75438 configFromInput(config); 75439 } 75440 75441 if (!isValid(config)) { 75442 config._d = null; 75443 } 75444 75445 return config; 75446 } 75447 75448 function configFromInput(config) { 75449 var input = config._i; 75450 if (isUndefined(input)) { 75451 config._d = new Date(hooks.now()); 75452 } else if (isDate(input)) { 75453 config._d = new Date(input.valueOf()); 75454 } else if (typeof input === 'string') { 75455 configFromString(config); 75456 } else if (isArray(input)) { 75457 config._a = map(input.slice(0), function (obj) { 75458 return parseInt(obj, 10); 75459 }); 75460 configFromArray(config); 75461 } else if (isObject(input)) { 75462 configFromObject(config); 75463 } else if (isNumber(input)) { 75464 // from milliseconds 75465 config._d = new Date(input); 75466 } else { 75467 hooks.createFromInputFallback(config); 75468 } 75469 } 75470 75471 function createLocalOrUTC (input, format, locale, strict, isUTC) { 75472 var c = {}; 75473 75474 if (locale === true || locale === false) { 75475 strict = locale; 75476 locale = undefined; 75477 } 75478 75479 if ((isObject(input) && isObjectEmpty(input)) || 75480 (isArray(input) && input.length === 0)) { 75481 input = undefined; 75482 } 75483 // object construction must be done this way. 75484 // https://github.com/moment/moment/issues/1423 75485 c._isAMomentObject = true; 75486 c._useUTC = c._isUTC = isUTC; 75487 c._l = locale; 75488 c._i = input; 75489 c._f = format; 75490 c._strict = strict; 75491 75492 return createFromConfig(c); 75493 } 75494 75495 function createLocal (input, format, locale, strict) { 75496 return createLocalOrUTC(input, format, locale, strict, false); 75497 } 75498 75499 var prototypeMin = deprecate( 75500 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', 75501 function () { 75502 var other = createLocal.apply(null, arguments); 75503 if (this.isValid() && other.isValid()) { 75504 return other < this ? this : other; 75505 } else { 75506 return createInvalid(); 75507 } 75508 } 75509 ); 75510 75511 var prototypeMax = deprecate( 75512 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', 75513 function () { 75514 var other = createLocal.apply(null, arguments); 75515 if (this.isValid() && other.isValid()) { 75516 return other > this ? this : other; 75517 } else { 75518 return createInvalid(); 75519 } 75520 } 75521 ); 75522 75523 // Pick a moment m from moments so that m[fn](other) is true for all 75524 // other. This relies on the function fn to be transitive. 75525 // 75526 // moments should either be an array of moment objects or an array, whose 75527 // first element is an array of moment objects. 75528 function pickBy(fn, moments) { 75529 var res, i; 75530 if (moments.length === 1 && isArray(moments[0])) { 75531 moments = moments[0]; 75532 } 75533 if (!moments.length) { 75534 return createLocal(); 75535 } 75536 res = moments[0]; 75537 for (i = 1; i < moments.length; ++i) { 75538 if (!moments[i].isValid() || moments[i][fn](res)) { 75539 res = moments[i]; 75540 } 75541 } 75542 return res; 75543 } 75544 75545 // TODO: Use [].sort instead? 75546 function min () { 75547 var args = [].slice.call(arguments, 0); 75548 75549 return pickBy('isBefore', args); 75550 } 75551 75552 function max () { 75553 var args = [].slice.call(arguments, 0); 75554 75555 return pickBy('isAfter', args); 75556 } 75557 75558 var now = function () { 75559 return Date.now ? Date.now() : +(new Date()); 75560 }; 75561 75562 var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond']; 75563 75564 function isDurationValid(m) { 75565 for (var key in m) { 75566 if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) { 75567 return false; 75568 } 75569 } 75570 75571 var unitHasDecimal = false; 75572 for (var i = 0; i < ordering.length; ++i) { 75573 if (m[ordering[i]]) { 75574 if (unitHasDecimal) { 75575 return false; // only allow non-integers for smallest unit 75576 } 75577 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) { 75578 unitHasDecimal = true; 75579 } 75580 } 75581 } 75582 75583 return true; 75584 } 75585 75586 function isValid$1() { 75587 return this._isValid; 75588 } 75589 75590 function createInvalid$1() { 75591 return createDuration(NaN); 75592 } 75593 75594 function Duration (duration) { 75595 var normalizedInput = normalizeObjectUnits(duration), 75596 years = normalizedInput.year || 0, 75597 quarters = normalizedInput.quarter || 0, 75598 months = normalizedInput.month || 0, 75599 weeks = normalizedInput.week || normalizedInput.isoWeek || 0, 75600 days = normalizedInput.day || 0, 75601 hours = normalizedInput.hour || 0, 75602 minutes = normalizedInput.minute || 0, 75603 seconds = normalizedInput.second || 0, 75604 milliseconds = normalizedInput.millisecond || 0; 75605 75606 this._isValid = isDurationValid(normalizedInput); 75607 75608 // representation for dateAddRemove 75609 this._milliseconds = +milliseconds + 75610 seconds * 1e3 + // 1000 75611 minutes * 6e4 + // 1000 * 60 75612 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 75613 // Because of dateAddRemove treats 24 hours as different from a 75614 // day when working around DST, we need to store them separately 75615 this._days = +days + 75616 weeks * 7; 75617 // It is impossible to translate months into days without knowing 75618 // which months you are are talking about, so we have to store 75619 // it separately. 75620 this._months = +months + 75621 quarters * 3 + 75622 years * 12; 75623 75624 this._data = {}; 75625 75626 this._locale = getLocale(); 75627 75628 this._bubble(); 75629 } 75630 75631 function isDuration (obj) { 75632 return obj instanceof Duration; 75633 } 75634 75635 function absRound (number) { 75636 if (number < 0) { 75637 return Math.round(-1 * number) * -1; 75638 } else { 75639 return Math.round(number); 75640 } 75641 } 75642 75643 // FORMATTING 75644 75645 function offset (token, separator) { 75646 addFormatToken(token, 0, 0, function () { 75647 var offset = this.utcOffset(); 75648 var sign = '+'; 75649 if (offset < 0) { 75650 offset = -offset; 75651 sign = '-'; 75652 } 75653 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); 75654 }); 75655 } 75656 75657 offset('Z', ':'); 75658 offset('ZZ', ''); 75659 75660 // PARSING 75661 75662 addRegexToken('Z', matchShortOffset); 75663 addRegexToken('ZZ', matchShortOffset); 75664 addParseToken(['Z', 'ZZ'], function (input, array, config) { 75665 config._useUTC = true; 75666 config._tzm = offsetFromString(matchShortOffset, input); 75667 }); 75668 75669 // HELPERS 75670 75671 // timezone chunker 75672 // '+10:00' > ['10', '00'] 75673 // '-1530' > ['-15', '30'] 75674 var chunkOffset = /([\+\-]|\d\d)/gi; 75675 75676 function offsetFromString(matcher, string) { 75677 var matches = (string || '').match(matcher); 75678 75679 if (matches === null) { 75680 return null; 75681 } 75682 75683 var chunk = matches[matches.length - 1] || []; 75684 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; 75685 var minutes = +(parts[1] * 60) + toInt(parts[2]); 75686 75687 return minutes === 0 ? 75688 0 : 75689 parts[0] === '+' ? minutes : -minutes; 75690 } 75691 75692 // Return a moment from input, that is local/utc/zone equivalent to model. 75693 function cloneWithOffset(input, model) { 75694 var res, diff; 75695 if (model._isUTC) { 75696 res = model.clone(); 75697 diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); 75698 // Use low-level api, because this fn is low-level api. 75699 res._d.setTime(res._d.valueOf() + diff); 75700 hooks.updateOffset(res, false); 75701 return res; 75702 } else { 75703 return createLocal(input).local(); 75704 } 75705 } 75706 75707 function getDateOffset (m) { 75708 // On Firefox.24 Date#getTimezoneOffset returns a floating point. 75709 // https://github.com/moment/moment/pull/1871 75710 return -Math.round(m._d.getTimezoneOffset() / 15) * 15; 75711 } 75712 75713 // HOOKS 75714 75715 // This function will be called whenever a moment is mutated. 75716 // It is intended to keep the offset in sync with the timezone. 75717 hooks.updateOffset = function () {}; 75718 75719 // MOMENTS 75720 75721 // keepLocalTime = true means only change the timezone, without 75722 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> 75723 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset 75724 // +0200, so we adjust the time as needed, to be valid. 75725 // 75726 // Keeping the time actually adds/subtracts (one hour) 75727 // from the actual represented time. That is why we call updateOffset 75728 // a second time. In case it wants us to change the offset again 75729 // _changeInProgress == true case, then we have to adjust, because 75730 // there is no such time in the given timezone. 75731 function getSetOffset (input, keepLocalTime, keepMinutes) { 75732 var offset = this._offset || 0, 75733 localAdjust; 75734 if (!this.isValid()) { 75735 return input != null ? this : NaN; 75736 } 75737 if (input != null) { 75738 if (typeof input === 'string') { 75739 input = offsetFromString(matchShortOffset, input); 75740 if (input === null) { 75741 return this; 75742 } 75743 } else if (Math.abs(input) < 16 && !keepMinutes) { 75744 input = input * 60; 75745 } 75746 if (!this._isUTC && keepLocalTime) { 75747 localAdjust = getDateOffset(this); 75748 } 75749 this._offset = input; 75750 this._isUTC = true; 75751 if (localAdjust != null) { 75752 this.add(localAdjust, 'm'); 75753 } 75754 if (offset !== input) { 75755 if (!keepLocalTime || this._changeInProgress) { 75756 addSubtract(this, createDuration(input - offset, 'm'), 1, false); 75757 } else if (!this._changeInProgress) { 75758 this._changeInProgress = true; 75759 hooks.updateOffset(this, true); 75760 this._changeInProgress = null; 75761 } 75762 } 75763 return this; 75764 } else { 75765 return this._isUTC ? offset : getDateOffset(this); 75766 } 75767 } 75768 75769 function getSetZone (input, keepLocalTime) { 75770 if (input != null) { 75771 if (typeof input !== 'string') { 75772 input = -input; 75773 } 75774 75775 this.utcOffset(input, keepLocalTime); 75776 75777 return this; 75778 } else { 75779 return -this.utcOffset(); 75780 } 75781 } 75782 75783 function setOffsetToUTC (keepLocalTime) { 75784 return this.utcOffset(0, keepLocalTime); 75785 } 75786 75787 function setOffsetToLocal (keepLocalTime) { 75788 if (this._isUTC) { 75789 this.utcOffset(0, keepLocalTime); 75790 this._isUTC = false; 75791 75792 if (keepLocalTime) { 75793 this.subtract(getDateOffset(this), 'm'); 75794 } 75795 } 75796 return this; 75797 } 75798 75799 function setOffsetToParsedOffset () { 75800 if (this._tzm != null) { 75801 this.utcOffset(this._tzm, false, true); 75802 } else if (typeof this._i === 'string') { 75803 var tZone = offsetFromString(matchOffset, this._i); 75804 if (tZone != null) { 75805 this.utcOffset(tZone); 75806 } 75807 else { 75808 this.utcOffset(0, true); 75809 } 75810 } 75811 return this; 75812 } 75813 75814 function hasAlignedHourOffset (input) { 75815 if (!this.isValid()) { 75816 return false; 75817 } 75818 input = input ? createLocal(input).utcOffset() : 0; 75819 75820 return (this.utcOffset() - input) % 60 === 0; 75821 } 75822 75823 function isDaylightSavingTime () { 75824 return ( 75825 this.utcOffset() > this.clone().month(0).utcOffset() || 75826 this.utcOffset() > this.clone().month(5).utcOffset() 75827 ); 75828 } 75829 75830 function isDaylightSavingTimeShifted () { 75831 if (!isUndefined(this._isDSTShifted)) { 75832 return this._isDSTShifted; 75833 } 75834 75835 var c = {}; 75836 75837 copyConfig(c, this); 75838 c = prepareConfig(c); 75839 75840 if (c._a) { 75841 var other = c._isUTC ? createUTC(c._a) : createLocal(c._a); 75842 this._isDSTShifted = this.isValid() && 75843 compareArrays(c._a, other.toArray()) > 0; 75844 } else { 75845 this._isDSTShifted = false; 75846 } 75847 75848 return this._isDSTShifted; 75849 } 75850 75851 function isLocal () { 75852 return this.isValid() ? !this._isUTC : false; 75853 } 75854 75855 function isUtcOffset () { 75856 return this.isValid() ? this._isUTC : false; 75857 } 75858 75859 function isUtc () { 75860 return this.isValid() ? this._isUTC && this._offset === 0 : false; 75861 } 75862 75863 // ASP.NET json date format regex 75864 var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; 75865 75866 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html 75867 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere 75868 // and further modified to allow for strings containing both week and day 75869 var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/; 75870 75871 function createDuration (input, key) { 75872 var duration = input, 75873 // matching against regexp is expensive, do it on demand 75874 match = null, 75875 sign, 75876 ret, 75877 diffRes; 75878 75879 if (isDuration(input)) { 75880 duration = { 75881 ms : input._milliseconds, 75882 d : input._days, 75883 M : input._months 75884 }; 75885 } else if (isNumber(input)) { 75886 duration = {}; 75887 if (key) { 75888 duration[key] = input; 75889 } else { 75890 duration.milliseconds = input; 75891 } 75892 } else if (!!(match = aspNetRegex.exec(input))) { 75893 sign = (match[1] === '-') ? -1 : 1; 75894 duration = { 75895 y : 0, 75896 d : toInt(match[DATE]) * sign, 75897 h : toInt(match[HOUR]) * sign, 75898 m : toInt(match[MINUTE]) * sign, 75899 s : toInt(match[SECOND]) * sign, 75900 ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match 75901 }; 75902 } else if (!!(match = isoRegex.exec(input))) { 75903 sign = (match[1] === '-') ? -1 : 1; 75904 duration = { 75905 y : parseIso(match[2], sign), 75906 M : parseIso(match[3], sign), 75907 w : parseIso(match[4], sign), 75908 d : parseIso(match[5], sign), 75909 h : parseIso(match[6], sign), 75910 m : parseIso(match[7], sign), 75911 s : parseIso(match[8], sign) 75912 }; 75913 } else if (duration == null) {// checks for null or undefined 75914 duration = {}; 75915 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { 75916 diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); 75917 75918 duration = {}; 75919 duration.ms = diffRes.milliseconds; 75920 duration.M = diffRes.months; 75921 } 75922 75923 ret = new Duration(duration); 75924 75925 if (isDuration(input) && hasOwnProp(input, '_locale')) { 75926 ret._locale = input._locale; 75927 } 75928 75929 return ret; 75930 } 75931 75932 createDuration.fn = Duration.prototype; 75933 createDuration.invalid = createInvalid$1; 75934 75935 function parseIso (inp, sign) { 75936 // We'd normally use ~~inp for this, but unfortunately it also 75937 // converts floats to ints. 75938 // inp may be undefined, so careful calling replace on it. 75939 var res = inp && parseFloat(inp.replace(',', '.')); 75940 // apply sign while we're at it 75941 return (isNaN(res) ? 0 : res) * sign; 75942 } 75943 75944 function positiveMomentsDifference(base, other) { 75945 var res = {}; 75946 75947 res.months = other.month() - base.month() + 75948 (other.year() - base.year()) * 12; 75949 if (base.clone().add(res.months, 'M').isAfter(other)) { 75950 --res.months; 75951 } 75952 75953 res.milliseconds = +other - +(base.clone().add(res.months, 'M')); 75954 75955 return res; 75956 } 75957 75958 function momentsDifference(base, other) { 75959 var res; 75960 if (!(base.isValid() && other.isValid())) { 75961 return {milliseconds: 0, months: 0}; 75962 } 75963 75964 other = cloneWithOffset(other, base); 75965 if (base.isBefore(other)) { 75966 res = positiveMomentsDifference(base, other); 75967 } else { 75968 res = positiveMomentsDifference(other, base); 75969 res.milliseconds = -res.milliseconds; 75970 res.months = -res.months; 75971 } 75972 75973 return res; 75974 } 75975 75976 // TODO: remove 'name' arg after deprecation is removed 75977 function createAdder(direction, name) { 75978 return function (val, period) { 75979 var dur, tmp; 75980 //invert the arguments, but complain about it 75981 if (period !== null && !isNaN(+period)) { 75982 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + 75983 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); 75984 tmp = val; val = period; period = tmp; 75985 } 75986 75987 val = typeof val === 'string' ? +val : val; 75988 dur = createDuration(val, period); 75989 addSubtract(this, dur, direction); 75990 return this; 75991 }; 75992 } 75993 75994 function addSubtract (mom, duration, isAdding, updateOffset) { 75995 var milliseconds = duration._milliseconds, 75996 days = absRound(duration._days), 75997 months = absRound(duration._months); 75998 75999 if (!mom.isValid()) { 76000 // No op 76001 return; 76002 } 76003 76004 updateOffset = updateOffset == null ? true : updateOffset; 76005 76006 if (months) { 76007 setMonth(mom, get(mom, 'Month') + months * isAdding); 76008 } 76009 if (days) { 76010 set$1(mom, 'Date', get(mom, 'Date') + days * isAdding); 76011 } 76012 if (milliseconds) { 76013 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); 76014 } 76015 if (updateOffset) { 76016 hooks.updateOffset(mom, days || months); 76017 } 76018 } 76019 76020 var add = createAdder(1, 'add'); 76021 var subtract = createAdder(-1, 'subtract'); 76022 76023 function getCalendarFormat(myMoment, now) { 76024 var diff = myMoment.diff(now, 'days', true); 76025 return diff < -6 ? 'sameElse' : 76026 diff < -1 ? 'lastWeek' : 76027 diff < 0 ? 'lastDay' : 76028 diff < 1 ? 'sameDay' : 76029 diff < 2 ? 'nextDay' : 76030 diff < 7 ? 'nextWeek' : 'sameElse'; 76031 } 76032 76033 function calendar$1 (time, formats) { 76034 // We want to compare the start of today, vs this. 76035 // Getting start-of-today depends on whether we're local/utc/offset or not. 76036 var now = time || createLocal(), 76037 sod = cloneWithOffset(now, this).startOf('day'), 76038 format = hooks.calendarFormat(this, sod) || 'sameElse'; 76039 76040 var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); 76041 76042 return this.format(output || this.localeData().calendar(format, this, createLocal(now))); 76043 } 76044 76045 function clone () { 76046 return new Moment(this); 76047 } 76048 76049 function isAfter (input, units) { 76050 var localInput = isMoment(input) ? input : createLocal(input); 76051 if (!(this.isValid() && localInput.isValid())) { 76052 return false; 76053 } 76054 units = normalizeUnits(units) || 'millisecond'; 76055 if (units === 'millisecond') { 76056 return this.valueOf() > localInput.valueOf(); 76057 } else { 76058 return localInput.valueOf() < this.clone().startOf(units).valueOf(); 76059 } 76060 } 76061 76062 function isBefore (input, units) { 76063 var localInput = isMoment(input) ? input : createLocal(input); 76064 if (!(this.isValid() && localInput.isValid())) { 76065 return false; 76066 } 76067 units = normalizeUnits(units) || 'millisecond'; 76068 if (units === 'millisecond') { 76069 return this.valueOf() < localInput.valueOf(); 76070 } else { 76071 return this.clone().endOf(units).valueOf() < localInput.valueOf(); 76072 } 76073 } 76074 76075 function isBetween (from, to, units, inclusivity) { 76076 var localFrom = isMoment(from) ? from : createLocal(from), 76077 localTo = isMoment(to) ? to : createLocal(to); 76078 if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) { 76079 return false; 76080 } 76081 inclusivity = inclusivity || '()'; 76082 return (inclusivity[0] === '(' ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && 76083 (inclusivity[1] === ')' ? this.isBefore(localTo, units) : !this.isAfter(localTo, units)); 76084 } 76085 76086 function isSame (input, units) { 76087 var localInput = isMoment(input) ? input : createLocal(input), 76088 inputMs; 76089 if (!(this.isValid() && localInput.isValid())) { 76090 return false; 76091 } 76092 units = normalizeUnits(units) || 'millisecond'; 76093 if (units === 'millisecond') { 76094 return this.valueOf() === localInput.valueOf(); 76095 } else { 76096 inputMs = localInput.valueOf(); 76097 return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); 76098 } 76099 } 76100 76101 function isSameOrAfter (input, units) { 76102 return this.isSame(input, units) || this.isAfter(input, units); 76103 } 76104 76105 function isSameOrBefore (input, units) { 76106 return this.isSame(input, units) || this.isBefore(input, units); 76107 } 76108 76109 function diff (input, units, asFloat) { 76110 var that, 76111 zoneDelta, 76112 output; 76113 76114 if (!this.isValid()) { 76115 return NaN; 76116 } 76117 76118 that = cloneWithOffset(input, this); 76119 76120 if (!that.isValid()) { 76121 return NaN; 76122 } 76123 76124 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; 76125 76126 units = normalizeUnits(units); 76127 76128 switch (units) { 76129 case 'year': output = monthDiff(this, that) / 12; break; 76130 case 'month': output = monthDiff(this, that); break; 76131 case 'quarter': output = monthDiff(this, that) / 3; break; 76132 case 'second': output = (this - that) / 1e3; break; // 1000 76133 case 'minute': output = (this - that) / 6e4; break; // 1000 * 60 76134 case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60 76135 case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst 76136 case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst 76137 default: output = this - that; 76138 } 76139 76140 return asFloat ? output : absFloor(output); 76141 } 76142 76143 function monthDiff (a, b) { 76144 // difference in months 76145 var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), 76146 // b is in (anchor - 1 month, anchor + 1 month) 76147 anchor = a.clone().add(wholeMonthDiff, 'months'), 76148 anchor2, adjust; 76149 76150 if (b - anchor < 0) { 76151 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); 76152 // linear across the month 76153 adjust = (b - anchor) / (anchor - anchor2); 76154 } else { 76155 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); 76156 // linear across the month 76157 adjust = (b - anchor) / (anchor2 - anchor); 76158 } 76159 76160 //check for negative zero, return zero if negative zero 76161 return -(wholeMonthDiff + adjust) || 0; 76162 } 76163 76164 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; 76165 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; 76166 76167 function toString () { 76168 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); 76169 } 76170 76171 function toISOString(keepOffset) { 76172 if (!this.isValid()) { 76173 return null; 76174 } 76175 var utc = keepOffset !== true; 76176 var m = utc ? this.clone().utc() : this; 76177 if (m.year() < 0 || m.year() > 9999) { 76178 return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'); 76179 } 76180 if (isFunction(Date.prototype.toISOString)) { 76181 // native implementation is ~50x faster, use it when we can 76182 if (utc) { 76183 return this.toDate().toISOString(); 76184 } else { 76185 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z')); 76186 } 76187 } 76188 return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'); 76189 } 76190 76191 /** 76192 * Return a human readable representation of a moment that can 76193 * also be evaluated to get a new moment which is the same 76194 * 76195 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects 76196 */ 76197 function inspect () { 76198 if (!this.isValid()) { 76199 return 'moment.invalid(/* ' + this._i + ' */)'; 76200 } 76201 var func = 'moment'; 76202 var zone = ''; 76203 if (!this.isLocal()) { 76204 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone'; 76205 zone = 'Z'; 76206 } 76207 var prefix = '[' + func + '("]'; 76208 var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY'; 76209 var datetime = '-MM-DD[T]HH:mm:ss.SSS'; 76210 var suffix = zone + '[")]'; 76211 76212 return this.format(prefix + year + datetime + suffix); 76213 } 76214 76215 function format (inputString) { 76216 if (!inputString) { 76217 inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat; 76218 } 76219 var output = formatMoment(this, inputString); 76220 return this.localeData().postformat(output); 76221 } 76222 76223 function from (time, withoutSuffix) { 76224 if (this.isValid() && 76225 ((isMoment(time) && time.isValid()) || 76226 createLocal(time).isValid())) { 76227 return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); 76228 } else { 76229 return this.localeData().invalidDate(); 76230 } 76231 } 76232 76233 function fromNow (withoutSuffix) { 76234 return this.from(createLocal(), withoutSuffix); 76235 } 76236 76237 function to (time, withoutSuffix) { 76238 if (this.isValid() && 76239 ((isMoment(time) && time.isValid()) || 76240 createLocal(time).isValid())) { 76241 return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); 76242 } else { 76243 return this.localeData().invalidDate(); 76244 } 76245 } 76246 76247 function toNow (withoutSuffix) { 76248 return this.to(createLocal(), withoutSuffix); 76249 } 76250 76251 // If passed a locale key, it will set the locale for this 76252 // instance. Otherwise, it will return the locale configuration 76253 // variables for this instance. 76254 function locale (key) { 76255 var newLocaleData; 76256 76257 if (key === undefined) { 76258 return this._locale._abbr; 76259 } else { 76260 newLocaleData = getLocale(key); 76261 if (newLocaleData != null) { 76262 this._locale = newLocaleData; 76263 } 76264 return this; 76265 } 76266 } 76267 76268 var lang = deprecate( 76269 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', 76270 function (key) { 76271 if (key === undefined) { 76272 return this.localeData(); 76273 } else { 76274 return this.locale(key); 76275 } 76276 } 76277 ); 76278 76279 function localeData () { 76280 return this._locale; 76281 } 76282 76283 var MS_PER_SECOND = 1000; 76284 var MS_PER_MINUTE = 60 * MS_PER_SECOND; 76285 var MS_PER_HOUR = 60 * MS_PER_MINUTE; 76286 var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR; 76287 76288 // actual modulo - handles negative numbers (for dates before 1970): 76289 function mod$1(dividend, divisor) { 76290 return (dividend % divisor + divisor) % divisor; 76291 } 76292 76293 function localStartOfDate(y, m, d) { 76294 // the date constructor remaps years 0-99 to 1900-1999 76295 if (y < 100 && y >= 0) { 76296 // preserve leap years using a full 400 year cycle, then reset 76297 return new Date(y + 400, m, d) - MS_PER_400_YEARS; 76298 } else { 76299 return new Date(y, m, d).valueOf(); 76300 } 76301 } 76302 76303 function utcStartOfDate(y, m, d) { 76304 // Date.UTC remaps years 0-99 to 1900-1999 76305 if (y < 100 && y >= 0) { 76306 // preserve leap years using a full 400 year cycle, then reset 76307 return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS; 76308 } else { 76309 return Date.UTC(y, m, d); 76310 } 76311 } 76312 76313 function startOf (units) { 76314 var time; 76315 units = normalizeUnits(units); 76316 if (units === undefined || units === 'millisecond' || !this.isValid()) { 76317 return this; 76318 } 76319 76320 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; 76321 76322 switch (units) { 76323 case 'year': 76324 time = startOfDate(this.year(), 0, 1); 76325 break; 76326 case 'quarter': 76327 time = startOfDate(this.year(), this.month() - this.month() % 3, 1); 76328 break; 76329 case 'month': 76330 time = startOfDate(this.year(), this.month(), 1); 76331 break; 76332 case 'week': 76333 time = startOfDate(this.year(), this.month(), this.date() - this.weekday()); 76334 break; 76335 case 'isoWeek': 76336 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1)); 76337 break; 76338 case 'day': 76339 case 'date': 76340 time = startOfDate(this.year(), this.month(), this.date()); 76341 break; 76342 case 'hour': 76343 time = this._d.valueOf(); 76344 time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR); 76345 break; 76346 case 'minute': 76347 time = this._d.valueOf(); 76348 time -= mod$1(time, MS_PER_MINUTE); 76349 break; 76350 case 'second': 76351 time = this._d.valueOf(); 76352 time -= mod$1(time, MS_PER_SECOND); 76353 break; 76354 } 76355 76356 this._d.setTime(time); 76357 hooks.updateOffset(this, true); 76358 return this; 76359 } 76360 76361 function endOf (units) { 76362 var time; 76363 units = normalizeUnits(units); 76364 if (units === undefined || units === 'millisecond' || !this.isValid()) { 76365 return this; 76366 } 76367 76368 var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate; 76369 76370 switch (units) { 76371 case 'year': 76372 time = startOfDate(this.year() + 1, 0, 1) - 1; 76373 break; 76374 case 'quarter': 76375 time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1; 76376 break; 76377 case 'month': 76378 time = startOfDate(this.year(), this.month() + 1, 1) - 1; 76379 break; 76380 case 'week': 76381 time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1; 76382 break; 76383 case 'isoWeek': 76384 time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1; 76385 break; 76386 case 'day': 76387 case 'date': 76388 time = startOfDate(this.year(), this.month(), this.date() + 1) - 1; 76389 break; 76390 case 'hour': 76391 time = this._d.valueOf(); 76392 time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1; 76393 break; 76394 case 'minute': 76395 time = this._d.valueOf(); 76396 time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1; 76397 break; 76398 case 'second': 76399 time = this._d.valueOf(); 76400 time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1; 76401 break; 76402 } 76403 76404 this._d.setTime(time); 76405 hooks.updateOffset(this, true); 76406 return this; 76407 } 76408 76409 function valueOf () { 76410 return this._d.valueOf() - ((this._offset || 0) * 60000); 76411 } 76412 76413 function unix () { 76414 return Math.floor(this.valueOf() / 1000); 76415 } 76416 76417 function toDate () { 76418 return new Date(this.valueOf()); 76419 } 76420 76421 function toArray () { 76422 var m = this; 76423 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; 76424 } 76425 76426 function toObject () { 76427 var m = this; 76428 return { 76429 years: m.year(), 76430 months: m.month(), 76431 date: m.date(), 76432 hours: m.hours(), 76433 minutes: m.minutes(), 76434 seconds: m.seconds(), 76435 milliseconds: m.milliseconds() 76436 }; 76437 } 76438 76439 function toJSON () { 76440 // new Date(NaN).toJSON() === null 76441 return this.isValid() ? this.toISOString() : null; 76442 } 76443 76444 function isValid$2 () { 76445 return isValid(this); 76446 } 76447 76448 function parsingFlags () { 76449 return extend({}, getParsingFlags(this)); 76450 } 76451 76452 function invalidAt () { 76453 return getParsingFlags(this).overflow; 76454 } 76455 76456 function creationData() { 76457 return { 76458 input: this._i, 76459 format: this._f, 76460 locale: this._locale, 76461 isUTC: this._isUTC, 76462 strict: this._strict 76463 }; 76464 } 76465 76466 // FORMATTING 76467 76468 addFormatToken(0, ['gg', 2], 0, function () { 76469 return this.weekYear() % 100; 76470 }); 76471 76472 addFormatToken(0, ['GG', 2], 0, function () { 76473 return this.isoWeekYear() % 100; 76474 }); 76475 76476 function addWeekYearFormatToken (token, getter) { 76477 addFormatToken(0, [token, token.length], 0, getter); 76478 } 76479 76480 addWeekYearFormatToken('gggg', 'weekYear'); 76481 addWeekYearFormatToken('ggggg', 'weekYear'); 76482 addWeekYearFormatToken('GGGG', 'isoWeekYear'); 76483 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); 76484 76485 // ALIASES 76486 76487 addUnitAlias('weekYear', 'gg'); 76488 addUnitAlias('isoWeekYear', 'GG'); 76489 76490 // PRIORITY 76491 76492 addUnitPriority('weekYear', 1); 76493 addUnitPriority('isoWeekYear', 1); 76494 76495 76496 // PARSING 76497 76498 addRegexToken('G', matchSigned); 76499 addRegexToken('g', matchSigned); 76500 addRegexToken('GG', match1to2, match2); 76501 addRegexToken('gg', match1to2, match2); 76502 addRegexToken('GGGG', match1to4, match4); 76503 addRegexToken('gggg', match1to4, match4); 76504 addRegexToken('GGGGG', match1to6, match6); 76505 addRegexToken('ggggg', match1to6, match6); 76506 76507 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { 76508 week[token.substr(0, 2)] = toInt(input); 76509 }); 76510 76511 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { 76512 week[token] = hooks.parseTwoDigitYear(input); 76513 }); 76514 76515 // MOMENTS 76516 76517 function getSetWeekYear (input) { 76518 return getSetWeekYearHelper.call(this, 76519 input, 76520 this.week(), 76521 this.weekday(), 76522 this.localeData()._week.dow, 76523 this.localeData()._week.doy); 76524 } 76525 76526 function getSetISOWeekYear (input) { 76527 return getSetWeekYearHelper.call(this, 76528 input, this.isoWeek(), this.isoWeekday(), 1, 4); 76529 } 76530 76531 function getISOWeeksInYear () { 76532 return weeksInYear(this.year(), 1, 4); 76533 } 76534 76535 function getWeeksInYear () { 76536 var weekInfo = this.localeData()._week; 76537 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); 76538 } 76539 76540 function getSetWeekYearHelper(input, week, weekday, dow, doy) { 76541 var weeksTarget; 76542 if (input == null) { 76543 return weekOfYear(this, dow, doy).year; 76544 } else { 76545 weeksTarget = weeksInYear(input, dow, doy); 76546 if (week > weeksTarget) { 76547 week = weeksTarget; 76548 } 76549 return setWeekAll.call(this, input, week, weekday, dow, doy); 76550 } 76551 } 76552 76553 function setWeekAll(weekYear, week, weekday, dow, doy) { 76554 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), 76555 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); 76556 76557 this.year(date.getUTCFullYear()); 76558 this.month(date.getUTCMonth()); 76559 this.date(date.getUTCDate()); 76560 return this; 76561 } 76562 76563 // FORMATTING 76564 76565 addFormatToken('Q', 0, 'Qo', 'quarter'); 76566 76567 // ALIASES 76568 76569 addUnitAlias('quarter', 'Q'); 76570 76571 // PRIORITY 76572 76573 addUnitPriority('quarter', 7); 76574 76575 // PARSING 76576 76577 addRegexToken('Q', match1); 76578 addParseToken('Q', function (input, array) { 76579 array[MONTH] = (toInt(input) - 1) * 3; 76580 }); 76581 76582 // MOMENTS 76583 76584 function getSetQuarter (input) { 76585 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); 76586 } 76587 76588 // FORMATTING 76589 76590 addFormatToken('D', ['DD', 2], 'Do', 'date'); 76591 76592 // ALIASES 76593 76594 addUnitAlias('date', 'D'); 76595 76596 // PRIORITY 76597 addUnitPriority('date', 9); 76598 76599 // PARSING 76600 76601 addRegexToken('D', match1to2); 76602 addRegexToken('DD', match1to2, match2); 76603 addRegexToken('Do', function (isStrict, locale) { 76604 // TODO: Remove "ordinalParse" fallback in next major release. 76605 return isStrict ? 76606 (locale._dayOfMonthOrdinalParse || locale._ordinalParse) : 76607 locale._dayOfMonthOrdinalParseLenient; 76608 }); 76609 76610 addParseToken(['D', 'DD'], DATE); 76611 addParseToken('Do', function (input, array) { 76612 array[DATE] = toInt(input.match(match1to2)[0]); 76613 }); 76614 76615 // MOMENTS 76616 76617 var getSetDayOfMonth = makeGetSet('Date', true); 76618 76619 // FORMATTING 76620 76621 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); 76622 76623 // ALIASES 76624 76625 addUnitAlias('dayOfYear', 'DDD'); 76626 76627 // PRIORITY 76628 addUnitPriority('dayOfYear', 4); 76629 76630 // PARSING 76631 76632 addRegexToken('DDD', match1to3); 76633 addRegexToken('DDDD', match3); 76634 addParseToken(['DDD', 'DDDD'], function (input, array, config) { 76635 config._dayOfYear = toInt(input); 76636 }); 76637 76638 // HELPERS 76639 76640 // MOMENTS 76641 76642 function getSetDayOfYear (input) { 76643 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; 76644 return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); 76645 } 76646 76647 // FORMATTING 76648 76649 addFormatToken('m', ['mm', 2], 0, 'minute'); 76650 76651 // ALIASES 76652 76653 addUnitAlias('minute', 'm'); 76654 76655 // PRIORITY 76656 76657 addUnitPriority('minute', 14); 76658 76659 // PARSING 76660 76661 addRegexToken('m', match1to2); 76662 addRegexToken('mm', match1to2, match2); 76663 addParseToken(['m', 'mm'], MINUTE); 76664 76665 // MOMENTS 76666 76667 var getSetMinute = makeGetSet('Minutes', false); 76668 76669 // FORMATTING 76670 76671 addFormatToken('s', ['ss', 2], 0, 'second'); 76672 76673 // ALIASES 76674 76675 addUnitAlias('second', 's'); 76676 76677 // PRIORITY 76678 76679 addUnitPriority('second', 15); 76680 76681 // PARSING 76682 76683 addRegexToken('s', match1to2); 76684 addRegexToken('ss', match1to2, match2); 76685 addParseToken(['s', 'ss'], SECOND); 76686 76687 // MOMENTS 76688 76689 var getSetSecond = makeGetSet('Seconds', false); 76690 76691 // FORMATTING 76692 76693 addFormatToken('S', 0, 0, function () { 76694 return ~~(this.millisecond() / 100); 76695 }); 76696 76697 addFormatToken(0, ['SS', 2], 0, function () { 76698 return ~~(this.millisecond() / 10); 76699 }); 76700 76701 addFormatToken(0, ['SSS', 3], 0, 'millisecond'); 76702 addFormatToken(0, ['SSSS', 4], 0, function () { 76703 return this.millisecond() * 10; 76704 }); 76705 addFormatToken(0, ['SSSSS', 5], 0, function () { 76706 return this.millisecond() * 100; 76707 }); 76708 addFormatToken(0, ['SSSSSS', 6], 0, function () { 76709 return this.millisecond() * 1000; 76710 }); 76711 addFormatToken(0, ['SSSSSSS', 7], 0, function () { 76712 return this.millisecond() * 10000; 76713 }); 76714 addFormatToken(0, ['SSSSSSSS', 8], 0, function () { 76715 return this.millisecond() * 100000; 76716 }); 76717 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { 76718 return this.millisecond() * 1000000; 76719 }); 76720 76721 76722 // ALIASES 76723 76724 addUnitAlias('millisecond', 'ms'); 76725 76726 // PRIORITY 76727 76728 addUnitPriority('millisecond', 16); 76729 76730 // PARSING 76731 76732 addRegexToken('S', match1to3, match1); 76733 addRegexToken('SS', match1to3, match2); 76734 addRegexToken('SSS', match1to3, match3); 76735 76736 var token; 76737 for (token = 'SSSS'; token.length <= 9; token += 'S') { 76738 addRegexToken(token, matchUnsigned); 76739 } 76740 76741 function parseMs(input, array) { 76742 array[MILLISECOND] = toInt(('0.' + input) * 1000); 76743 } 76744 76745 for (token = 'S'; token.length <= 9; token += 'S') { 76746 addParseToken(token, parseMs); 76747 } 76748 // MOMENTS 76749 76750 var getSetMillisecond = makeGetSet('Milliseconds', false); 76751 76752 // FORMATTING 76753 76754 addFormatToken('z', 0, 0, 'zoneAbbr'); 76755 addFormatToken('zz', 0, 0, 'zoneName'); 76756 76757 // MOMENTS 76758 76759 function getZoneAbbr () { 76760 return this._isUTC ? 'UTC' : ''; 76761 } 76762 76763 function getZoneName () { 76764 return this._isUTC ? 'Coordinated Universal Time' : ''; 76765 } 76766 76767 var proto = Moment.prototype; 76768 76769 proto.add = add; 76770 proto.calendar = calendar$1; 76771 proto.clone = clone; 76772 proto.diff = diff; 76773 proto.endOf = endOf; 76774 proto.format = format; 76775 proto.from = from; 76776 proto.fromNow = fromNow; 76777 proto.to = to; 76778 proto.toNow = toNow; 76779 proto.get = stringGet; 76780 proto.invalidAt = invalidAt; 76781 proto.isAfter = isAfter; 76782 proto.isBefore = isBefore; 76783 proto.isBetween = isBetween; 76784 proto.isSame = isSame; 76785 proto.isSameOrAfter = isSameOrAfter; 76786 proto.isSameOrBefore = isSameOrBefore; 76787 proto.isValid = isValid$2; 76788 proto.lang = lang; 76789 proto.locale = locale; 76790 proto.localeData = localeData; 76791 proto.max = prototypeMax; 76792 proto.min = prototypeMin; 76793 proto.parsingFlags = parsingFlags; 76794 proto.set = stringSet; 76795 proto.startOf = startOf; 76796 proto.subtract = subtract; 76797 proto.toArray = toArray; 76798 proto.toObject = toObject; 76799 proto.toDate = toDate; 76800 proto.toISOString = toISOString; 76801 proto.inspect = inspect; 76802 proto.toJSON = toJSON; 76803 proto.toString = toString; 76804 proto.unix = unix; 76805 proto.valueOf = valueOf; 76806 proto.creationData = creationData; 76807 proto.year = getSetYear; 76808 proto.isLeapYear = getIsLeapYear; 76809 proto.weekYear = getSetWeekYear; 76810 proto.isoWeekYear = getSetISOWeekYear; 76811 proto.quarter = proto.quarters = getSetQuarter; 76812 proto.month = getSetMonth; 76813 proto.daysInMonth = getDaysInMonth; 76814 proto.week = proto.weeks = getSetWeek; 76815 proto.isoWeek = proto.isoWeeks = getSetISOWeek; 76816 proto.weeksInYear = getWeeksInYear; 76817 proto.isoWeeksInYear = getISOWeeksInYear; 76818 proto.date = getSetDayOfMonth; 76819 proto.day = proto.days = getSetDayOfWeek; 76820 proto.weekday = getSetLocaleDayOfWeek; 76821 proto.isoWeekday = getSetISODayOfWeek; 76822 proto.dayOfYear = getSetDayOfYear; 76823 proto.hour = proto.hours = getSetHour; 76824 proto.minute = proto.minutes = getSetMinute; 76825 proto.second = proto.seconds = getSetSecond; 76826 proto.millisecond = proto.milliseconds = getSetMillisecond; 76827 proto.utcOffset = getSetOffset; 76828 proto.utc = setOffsetToUTC; 76829 proto.local = setOffsetToLocal; 76830 proto.parseZone = setOffsetToParsedOffset; 76831 proto.hasAlignedHourOffset = hasAlignedHourOffset; 76832 proto.isDST = isDaylightSavingTime; 76833 proto.isLocal = isLocal; 76834 proto.isUtcOffset = isUtcOffset; 76835 proto.isUtc = isUtc; 76836 proto.isUTC = isUtc; 76837 proto.zoneAbbr = getZoneAbbr; 76838 proto.zoneName = getZoneName; 76839 proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); 76840 proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); 76841 proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); 76842 proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); 76843 proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); 76844 76845 function createUnix (input) { 76846 return createLocal(input * 1000); 76847 } 76848 76849 function createInZone () { 76850 return createLocal.apply(null, arguments).parseZone(); 76851 } 76852 76853 function preParsePostFormat (string) { 76854 return string; 76855 } 76856 76857 var proto$1 = Locale.prototype; 76858 76859 proto$1.calendar = calendar; 76860 proto$1.longDateFormat = longDateFormat; 76861 proto$1.invalidDate = invalidDate; 76862 proto$1.ordinal = ordinal; 76863 proto$1.preparse = preParsePostFormat; 76864 proto$1.postformat = preParsePostFormat; 76865 proto$1.relativeTime = relativeTime; 76866 proto$1.pastFuture = pastFuture; 76867 proto$1.set = set; 76868 76869 proto$1.months = localeMonths; 76870 proto$1.monthsShort = localeMonthsShort; 76871 proto$1.monthsParse = localeMonthsParse; 76872 proto$1.monthsRegex = monthsRegex; 76873 proto$1.monthsShortRegex = monthsShortRegex; 76874 proto$1.week = localeWeek; 76875 proto$1.firstDayOfYear = localeFirstDayOfYear; 76876 proto$1.firstDayOfWeek = localeFirstDayOfWeek; 76877 76878 proto$1.weekdays = localeWeekdays; 76879 proto$1.weekdaysMin = localeWeekdaysMin; 76880 proto$1.weekdaysShort = localeWeekdaysShort; 76881 proto$1.weekdaysParse = localeWeekdaysParse; 76882 76883 proto$1.weekdaysRegex = weekdaysRegex; 76884 proto$1.weekdaysShortRegex = weekdaysShortRegex; 76885 proto$1.weekdaysMinRegex = weekdaysMinRegex; 76886 76887 proto$1.isPM = localeIsPM; 76888 proto$1.meridiem = localeMeridiem; 76889 76890 function get$1 (format, index, field, setter) { 76891 var locale = getLocale(); 76892 var utc = createUTC().set(setter, index); 76893 return locale[field](utc, format); 76894 } 76895 76896 function listMonthsImpl (format, index, field) { 76897 if (isNumber(format)) { 76898 index = format; 76899 format = undefined; 76900 } 76901 76902 format = format || ''; 76903 76904 if (index != null) { 76905 return get$1(format, index, field, 'month'); 76906 } 76907 76908 var i; 76909 var out = []; 76910 for (i = 0; i < 12; i++) { 76911 out[i] = get$1(format, i, field, 'month'); 76912 } 76913 return out; 76914 } 76915 76916 // () 76917 // (5) 76918 // (fmt, 5) 76919 // (fmt) 76920 // (true) 76921 // (true, 5) 76922 // (true, fmt, 5) 76923 // (true, fmt) 76924 function listWeekdaysImpl (localeSorted, format, index, field) { 76925 if (typeof localeSorted === 'boolean') { 76926 if (isNumber(format)) { 76927 index = format; 76928 format = undefined; 76929 } 76930 76931 format = format || ''; 76932 } else { 76933 format = localeSorted; 76934 index = format; 76935 localeSorted = false; 76936 76937 if (isNumber(format)) { 76938 index = format; 76939 format = undefined; 76940 } 76941 76942 format = format || ''; 76943 } 76944 76945 var locale = getLocale(), 76946 shift = localeSorted ? locale._week.dow : 0; 76947 76948 if (index != null) { 76949 return get$1(format, (index + shift) % 7, field, 'day'); 76950 } 76951 76952 var i; 76953 var out = []; 76954 for (i = 0; i < 7; i++) { 76955 out[i] = get$1(format, (i + shift) % 7, field, 'day'); 76956 } 76957 return out; 76958 } 76959 76960 function listMonths (format, index) { 76961 return listMonthsImpl(format, index, 'months'); 76962 } 76963 76964 function listMonthsShort (format, index) { 76965 return listMonthsImpl(format, index, 'monthsShort'); 76966 } 76967 76968 function listWeekdays (localeSorted, format, index) { 76969 return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); 76970 } 76971 76972 function listWeekdaysShort (localeSorted, format, index) { 76973 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); 76974 } 76975 76976 function listWeekdaysMin (localeSorted, format, index) { 76977 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); 76978 } 76979 76980 getSetGlobalLocale('en', { 76981 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, 76982 ordinal : function (number) { 76983 var b = number % 10, 76984 output = (toInt(number % 100 / 10) === 1) ? 'th' : 76985 (b === 1) ? 'st' : 76986 (b === 2) ? 'nd' : 76987 (b === 3) ? 'rd' : 'th'; 76988 return number + output; 76989 } 76990 }); 76991 76992 // Side effect imports 76993 76994 hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); 76995 hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); 76996 76997 var mathAbs = Math.abs; 76998 76999 function abs () { 77000 var data = this._data; 77001 77002 this._milliseconds = mathAbs(this._milliseconds); 77003 this._days = mathAbs(this._days); 77004 this._months = mathAbs(this._months); 77005 77006 data.milliseconds = mathAbs(data.milliseconds); 77007 data.seconds = mathAbs(data.seconds); 77008 data.minutes = mathAbs(data.minutes); 77009 data.hours = mathAbs(data.hours); 77010 data.months = mathAbs(data.months); 77011 data.years = mathAbs(data.years); 77012 77013 return this; 77014 } 77015 77016 function addSubtract$1 (duration, input, value, direction) { 77017 var other = createDuration(input, value); 77018 77019 duration._milliseconds += direction * other._milliseconds; 77020 duration._days += direction * other._days; 77021 duration._months += direction * other._months; 77022 77023 return duration._bubble(); 77024 } 77025 77026 // supports only 2.0-style add(1, 's') or add(duration) 77027 function add$1 (input, value) { 77028 return addSubtract$1(this, input, value, 1); 77029 } 77030 77031 // supports only 2.0-style subtract(1, 's') or subtract(duration) 77032 function subtract$1 (input, value) { 77033 return addSubtract$1(this, input, value, -1); 77034 } 77035 77036 function absCeil (number) { 77037 if (number < 0) { 77038 return Math.floor(number); 77039 } else { 77040 return Math.ceil(number); 77041 } 77042 } 77043 77044 function bubble () { 77045 var milliseconds = this._milliseconds; 77046 var days = this._days; 77047 var months = this._months; 77048 var data = this._data; 77049 var seconds, minutes, hours, years, monthsFromDays; 77050 77051 // if we have a mix of positive and negative values, bubble down first 77052 // check: https://github.com/moment/moment/issues/2166 77053 if (!((milliseconds >= 0 && days >= 0 && months >= 0) || 77054 (milliseconds <= 0 && days <= 0 && months <= 0))) { 77055 milliseconds += absCeil(monthsToDays(months) + days) * 864e5; 77056 days = 0; 77057 months = 0; 77058 } 77059 77060 // The following code bubbles up values, see the tests for 77061 // examples of what that means. 77062 data.milliseconds = milliseconds % 1000; 77063 77064 seconds = absFloor(milliseconds / 1000); 77065 data.seconds = seconds % 60; 77066 77067 minutes = absFloor(seconds / 60); 77068 data.minutes = minutes % 60; 77069 77070 hours = absFloor(minutes / 60); 77071 data.hours = hours % 24; 77072 77073 days += absFloor(hours / 24); 77074 77075 // convert days to months 77076 monthsFromDays = absFloor(daysToMonths(days)); 77077 months += monthsFromDays; 77078 days -= absCeil(monthsToDays(monthsFromDays)); 77079 77080 // 12 months -> 1 year 77081 years = absFloor(months / 12); 77082 months %= 12; 77083 77084 data.days = days; 77085 data.months = months; 77086 data.years = years; 77087 77088 return this; 77089 } 77090 77091 function daysToMonths (days) { 77092 // 400 years have 146097 days (taking into account leap year rules) 77093 // 400 years have 12 months === 4800 77094 return days * 4800 / 146097; 77095 } 77096 77097 function monthsToDays (months) { 77098 // the reverse of daysToMonths 77099 return months * 146097 / 4800; 77100 } 77101 77102 function as (units) { 77103 if (!this.isValid()) { 77104 return NaN; 77105 } 77106 var days; 77107 var months; 77108 var milliseconds = this._milliseconds; 77109 77110 units = normalizeUnits(units); 77111 77112 if (units === 'month' || units === 'quarter' || units === 'year') { 77113 days = this._days + milliseconds / 864e5; 77114 months = this._months + daysToMonths(days); 77115 switch (units) { 77116 case 'month': return months; 77117 case 'quarter': return months / 3; 77118 case 'year': return months / 12; 77119 } 77120 } else { 77121 // handle milliseconds separately because of floating point math errors (issue #1867) 77122 days = this._days + Math.round(monthsToDays(this._months)); 77123 switch (units) { 77124 case 'week' : return days / 7 + milliseconds / 6048e5; 77125 case 'day' : return days + milliseconds / 864e5; 77126 case 'hour' : return days * 24 + milliseconds / 36e5; 77127 case 'minute' : return days * 1440 + milliseconds / 6e4; 77128 case 'second' : return days * 86400 + milliseconds / 1000; 77129 // Math.floor prevents floating point math errors here 77130 case 'millisecond': return Math.floor(days * 864e5) + milliseconds; 77131 default: throw new Error('Unknown unit ' + units); 77132 } 77133 } 77134 } 77135 77136 // TODO: Use this.as('ms')? 77137 function valueOf$1 () { 77138 if (!this.isValid()) { 77139 return NaN; 77140 } 77141 return ( 77142 this._milliseconds + 77143 this._days * 864e5 + 77144 (this._months % 12) * 2592e6 + 77145 toInt(this._months / 12) * 31536e6 77146 ); 77147 } 77148 77149 function makeAs (alias) { 77150 return function () { 77151 return this.as(alias); 77152 }; 77153 } 77154 77155 var asMilliseconds = makeAs('ms'); 77156 var asSeconds = makeAs('s'); 77157 var asMinutes = makeAs('m'); 77158 var asHours = makeAs('h'); 77159 var asDays = makeAs('d'); 77160 var asWeeks = makeAs('w'); 77161 var asMonths = makeAs('M'); 77162 var asQuarters = makeAs('Q'); 77163 var asYears = makeAs('y'); 77164 77165 function clone$1 () { 77166 return createDuration(this); 77167 } 77168 77169 function get$2 (units) { 77170 units = normalizeUnits(units); 77171 return this.isValid() ? this[units + 's']() : NaN; 77172 } 77173 77174 function makeGetter(name) { 77175 return function () { 77176 return this.isValid() ? this._data[name] : NaN; 77177 }; 77178 } 77179 77180 var milliseconds = makeGetter('milliseconds'); 77181 var seconds = makeGetter('seconds'); 77182 var minutes = makeGetter('minutes'); 77183 var hours = makeGetter('hours'); 77184 var days = makeGetter('days'); 77185 var months = makeGetter('months'); 77186 var years = makeGetter('years'); 77187 77188 function weeks () { 77189 return absFloor(this.days() / 7); 77190 } 77191 77192 var round = Math.round; 77193 var thresholds = { 77194 ss: 44, // a few seconds to seconds 77195 s : 45, // seconds to minute 77196 m : 45, // minutes to hour 77197 h : 22, // hours to day 77198 d : 26, // days to month 77199 M : 11 // months to year 77200 }; 77201 77202 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize 77203 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { 77204 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); 77205 } 77206 77207 function relativeTime$1 (posNegDuration, withoutSuffix, locale) { 77208 var duration = createDuration(posNegDuration).abs(); 77209 var seconds = round(duration.as('s')); 77210 var minutes = round(duration.as('m')); 77211 var hours = round(duration.as('h')); 77212 var days = round(duration.as('d')); 77213 var months = round(duration.as('M')); 77214 var years = round(duration.as('y')); 77215 77216 var a = seconds <= thresholds.ss && ['s', seconds] ||
77217 seconds < thresholds.s && ['ss', seconds] || 77218 minutes <= 1 && ['m'] || 77219 minutes < thresholds.m && ['mm', minutes] || 77220 hours <= 1 && ['h'] || 77221 hours < thresholds.h && ['hh', hours] || 77222 days <= 1 && ['d'] || 77223 days < thresholds.d && ['dd', days] || 77224 months <= 1 && ['M'] || 77225 months < thresholds.M && ['MM', months] || 77226 years <= 1 && ['y'] || ['yy', years]; 77227 77228 a[2] = withoutSuffix; 77229 a[3] = +posNegDuration > 0; 77230 a[4] = locale; 77231 return substituteTimeAgo.apply(null, a); 77232 } 77233 77234 // This function allows you to set the rounding function for relative time strings 77235 function getSetRelativeTimeRounding (roundingFunction) { 77236 if (roundingFunction === undefined) { 77237 return round; 77238 } 77239 if (typeof(rou
77239ndingFunction) === 'function') { 77240 round = roundingFunction; 77241 return true; 77242 } 77243 return false; 77244 } 77245 77246 // This function allows you to set a threshold for relative time strings 77247 function getSetRelativeTimeThreshold (threshold, limit) { 77248 if (thresholds[threshold] === undefined) { 77249 return false; 77250 } 77251 if (limit === undefined) { 77252 return thresholds[threshold]; 77253 } 77254 thresholds[threshold] = limit; 77255 if (threshold === 's') { 77256 thresholds.ss = limit - 1; 77257 } 77258 return true; 77259 } 77260 77261 function humanize (withSuffix) { 77262 if (!this.isValid()) { 77263 return this.localeData().invalidDate(); 77264 } 77265 77266 var locale = this.localeData(); 77267 var output = relativeTime$1(this, !withSuffix, locale); 77268 77269 if (withSuffix) { 77270 output = locale.pastFuture(+this, output); 77271 } 77272 77273 return locale.postformat(output); 77274 } 77275 77276 var abs$1 = Math.abs; 77277 77278 function sign(x) { 77279 return ((x > 0) - (x < 0)) || +x; 77280 } 77281 77282 function toISOString$1() { 77283 // for ISO strings we do not use the normal bubbling rules: 77284 // * milliseconds bubble up until they become hours 77285 // * days do not bubble at all 77286 // * months bubble up until they become years 77287 // This is because there is no context-free conversion between hours and days 77288 // (think of clock changes) 77289 // and also not between days and months (28-31 days per month) 77290 if (!this.isValid()) { 77291 return this.localeData().invalidDate(); 77292 } 77293 77294 var seconds = abs$1(this._milliseconds) / 1000; 77295 var days = abs$1(this._days); 77296 var months = abs$1(this._months); 77297 var minutes, hours, years; 77298 77299 // 3600 seconds -> 60 minutes -> 1 hour 77300 minutes = absFloor(seconds / 60); 77301 hours = absFloor(minutes / 60); 77302 seconds %= 60; 77303 minutes %= 60; 77304 77305 // 12 months -> 1 year 77306 years = absFloor(months / 12); 77307 months %= 12; 77308 77309 77310 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js 77311 var Y = years; 77312 var M = months; 77313 var D = days; 77314 var h = hours; 77315 var m = minutes; 77316 var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : ''; 77317 var total = this.asSeconds(); 77318 77319 if (!total) { 77320 // this is the same as C#'s (Noda) and python (isodate)... 77321 // but not other JS (goog.date) 77322 return 'P0D'; 77323 } 77324 77325 var totalSign = total < 0 ? '-' : ''; 77326 var ymSign = sign(this._months) !== sign(total) ? '-' : ''; 77327 var daysSign = sign(this._days) !== sign(total) ? '-' : ''; 77328 var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : ''; 77329 77330 return totalSign + 'P' + 77331 (Y ? ymSign + Y + 'Y' : '') + 77332 (M ? ymSign + M + 'M' : '') + 77333 (D ? daysSign + D + 'D' : '') + 77334 ((h || m || s) ? 'T' : '') + 77335 (h ? hmsSign + h + 'H' : '') + 77336 (m ? hmsSign + m + 'M' : '') + 77337 (s ? hmsSign + s + 'S' : ''); 77338 } 77339 77340 var proto$2 = Duration.prototype; 77341 77342 proto$2.isValid = isValid$1; 77343 proto$2.abs = abs; 77344 proto$2.add = add$1; 77345 proto$2.subtract = subtract$1; 77346 proto$2.as = as; 77347 proto$2.asMilliseconds = asMilliseconds; 77348 proto$2.asSeconds = asSeconds; 77349 proto$2.asMinutes = asMinutes; 77350 proto$2.asHours = asHours; 77351 proto$2.asDays = asDays; 77352 proto$2.asWeeks = asWeeks; 77353 proto$2.asMonths = asMonths; 77354 proto$2.asQuarters = asQuarters; 77355 proto$2.asYears = asYears; 77356 proto$2.valueOf = valueOf$1; 77357 proto$2._bubble = bubble; 77358 proto$2.clone = clone$1; 77359 proto$2.get = get$2; 77360 proto$2.milliseconds = milliseconds; 77361 proto$2.seconds = seconds; 77362 proto$2.minutes = minutes; 77363 proto$2.hours = hours; 77364 proto$2.days = days; 77365 proto$2.weeks = weeks; 77366 proto$2.months = months; 77367 proto$2.years = years; 77368 proto$2.humanize = humanize; 77369 proto$2.toISOString = toISOString$1; 77370 proto$2.toString = toISOString$1; 77371 proto$2.toJSON = toISOString$1; 77372 proto$2.locale = locale; 77373 proto$2.localeData = localeData; 77374 77375 proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1); 77376 proto$2.lang = lang; 77377 77378 // Side effect imports 77379 77380 // FORMATTING 77381 77382 addFormatToken('X', 0, 0, 'unix'); 77383 addFormatToken('x', 0, 0, 'valueOf'); 77384 77385 // PARSING 77386 77387 addRegexToken('x', matchSigned); 77388 addRegexToken('X', matchTimestamp); 77389 addParseToken('X', function (input, array, config) { 77390 config._d = new Date(parseFloat(input, 10) * 1000); 77391 }); 77392 addParseToken('x', function (input, array, config) { 77393 config._d = new Date(toInt(input)); 77394 }); 77395 77396 // Side effect imports 77397 77398 77399 hooks.version = '2.24.0'; 77400 77401 setHookCallback(createLocal); 77402 77403 hooks.fn = proto; 77404 hooks.min = min; 77405 hooks.max = max; 77406 hooks.now = now; 77407 hooks.utc = createUTC; 77408 hooks.unix = createUnix; 77409 hooks.months = listMonths; 77410 hooks.isDate = isDate; 77411 hooks.locale = getSetGlobalLocale; 77412 hooks.invalid = createInvalid; 77413 hooks.duration = createDuration; 77414 hooks.isMoment = isMoment; 77415 hooks.weekdays = listWeekdays; 77416 hooks.parseZone = createInZone; 77417 hooks.localeData = getLocale; 77418 hooks.isDuration = isDuration; 77419 hooks.monthsShort = listMonthsShort; 77420 hooks.weekdaysMin = listWeekdaysMin; 77421 hooks.defineLocale = defineLocale; 77422 hooks.updateLocale = updateLocale; 77423 hooks.locales = listLocales; 77424 hooks.weekdaysShort = listWeekdaysShort; 77425 hooks.normalizeUnits = normalizeUnits; 77426 hooks.relativeTimeRounding = getSetRelativeTimeRounding; 77427 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold; 77428 hooks.calendarFormat = getCalendarFormat; 77429 hooks.prototype = proto; 77430 77431 // currently HTML5 input type only supports 24-hour formats 77432 hooks.HTML5_FMT = { 77433 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" /> 77434 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" /> 77435 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" /> 77436 DATE: 'YYYY-MM-DD', // <input type="date" /> 77437 TIME: 'HH:mm', // <input type="time" /> 77438 TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" /> 77439 TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" /> 77440 WEEK: 'GGGG-[W]WW', // <input type="week" /> 77441 MONTH: 'YYYY-MM' // <input type="month" /> 77442 }; 77443 77444 return hooks; 77445 77446}))); 77447}); 77448 77449var FORMATS = { 77450 datetime: 'MMM D, YYYY, h:mm:ss a', 77451 millisecond: 'h:mm:ss.SSS a', 77452 second: 'h:mm:ss a', 77453 minute: 'h:mm a', 77454 hour: 'hA', 77455 day: 'MMM D', 77456 week: 'll', 77457 month: 'MMM YYYY', 77458 quarter: '[Q]Q - YYYY', 77459 year: 'YYYY' 77460}; 77461 77462core_adapters._date.override(typeof moment === 'function' ? { 77463 _id: 'moment', // DEBUG ONLY 77464 77465 formats: function() { 77466 return FORMATS; 77467 }, 77468 77469 parse: function(value, format) { 77470 if (typeof value === 'string' && typeof format === 'string') { 77471 value = moment(value, format); 77472 } else if (!(value instanceof moment)) { 77473 value = moment(value); 77474 } 77475 return value.isValid() ? value.valueOf() : null; 77476 }, 77477 77478 format: function(time, format) { 77479 return moment(time).format(format); 77480 }, 77481 77482 add: function(time, amount, unit) { 77483 return moment(time).add(amount, unit).valueOf(); 77484 }, 77485 77486 diff: function(max, min, unit) { 77487 return moment.duration(moment(max).diff(moment(min))).as(unit); 77488 }, 77489 77490 startOf: function(time, unit, weekday) { 77491 time = moment(time); 77492 if (unit === 'isoWeek') { 77493 return time.isoWeekday(weekday).valueOf(); 77494 } 77495 return time.startOf(unit).valueOf(); 77496 }, 77497 77498 endOf: function(time, unit) { 77499 return moment(time).endOf(unit).valueOf(); 77500 }, 77501 77502 // DEPRECATIONS 77503 77504 /** 77505 * Provided for backward compatibility with scale.getValueForPixel(). 77506 * @deprecated since version 2.8.0 77507 * @todo remove at version 3 77508 * @private 77509 */ 77510 _create: function(time) { 77511 return moment(time); 77512 }, 77513} : {}); 77514 77515core_defaults._set('global', { 77516 plugins: { 77517 filler: { 77518 propagate: true 77519 } 77520 } 77521}); 77522 77523var mappers = { 77524 dataset: function(source) { 77525 var index = source.fill; 77526 var chart = source.chart; 77527 var meta = chart.getDatasetMeta(index); 77528 var visible = meta && chart.isDatasetVisible(index); 77529 var points = (visible && meta.dataset._children) || []; 77530 var length = points.length || 0; 77531 77532 return !length ? null : function(point, i) { 77533 return (i < length && points[i]._view) || null; 77534 }; 77535 }, 77536
vendor: 4,419 bytes, lines 77537-77764
77537 boundary: function(source) { 77538 var boundary = source.boundary; 77539 var x = boundary ? boundary.x : null; 77540 var y = boundary ? boundary.y : null; 77541 77542 return function(point) { 77543 return { 77544 x: x === null ? point.x : x, 77545 y: y === null ? point.y : y, 77546 }; 77547 }; 77548 } 77549}; 77550 77551// @todo if (fill[0] === '#') 77552function decodeFill(el, index, count) { 77553 var model = el._model || {}; 77554 var fill = model.fill; 77555 var target; 77556 77557 if (fill === undefined) { 77558 fill = !!model.backgroundColor; 77559 } 77560 77561 if (fill === false || fill === null) { 77562 return false; 77563 } 77564 77565 if (fill === true) { 77566 return 'origin'; 77567 } 77568 77569 target = parseFloat(fill, 10); 77570 if (isFinite(target) && Math.floor(target) === target) { 77571 if (fill[0] === '-' || fill[0] === '+') { 77572 target = index + target; 77573 } 77574 77575 if (target === index || target < 0 || target >= count) { 77576 return false; 77577 } 77578 77579 return target; 77580 } 77581 77582 switch (fill) { 77583 // compatibility 77584 case 'bottom': 77585 return 'start'; 77586 case 'top': 77587 return 'end'; 77588 case 'zero': 77589 return 'origin'; 77590 // supported boundaries 77591 case 'origin': 77592 case 'start': 77593 case 'end': 77594 return fill; 77595 // invalid fill values 77596 default: 77597 return false; 77598 } 77599} 77600 77601function computeBoundary(source) { 77602 var model = source.el._model || {}; 77603 var scale = source.el._scale || {}; 77604 var fill = source.fill; 77605 var target = null; 77606 var horizontal; 77607 77608 if (isFinite(fill)) { 77609 return null; 77610 } 77611 77612 // Backward compatibility: until v3, we still need to support boundary values set on 77613 // the model (scaleTop, scaleBottom and scaleZero) because some external plugins and 77614 // controllers might still use it (e.g. the Smith chart). 77615 77616 if (fill === 'start') { 77617 target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom; 77618 } else if (fill === 'end') { 77619 target = model.scaleTop === undefined ? scale.top : model.scaleTop; 77620 } else if (model.scaleZero !== undefined) { 77621 target = model.scaleZero; 77622 } else if (scale.getBasePosition) { 77623 target = scale.getBasePosition(); 77624 } else if (scale.getBasePixel) { 77625 target = scale.getBasePixel(); 77626 } 77627 77628 if (target !== undefined && target !== null) { 77629 if (target.x !== undefined && target.y !== undefined) { 77630 return target; 77631 } 77632 77633 if (helpers$1.isFinite(target)) { 77634 horizontal = scale.isHorizontal(); 77635 return { 77636 x: horizontal ? target : null, 77637 y: horizontal ? null : target 77638 }; 77639 } 77640 } 77641 77642 return null; 77643} 77644 77645function resolveTarget(sources, index, propagate) { 77646 var source = sources[index]; 77647 var fill = source.fill; 77648 var visited = [index]; 77649 var target; 77650 77651 if (!propagate) { 77652 return fill; 77653 } 77654 77655 while (fill !== false && visited.indexOf(fill) === -1) { 77656 if (!isFinite(fill)) { 77657 return fill; 77658 } 77659 77660 target = sources[fill]; 77661 if (!target) { 77662 return false; 77663 } 77664 77665 if (target.visible) { 77666 return fill; 77667 } 77668 77669 visited.push(fill); 77670 fill = target.fill; 77671 } 77672 77673 return false; 77674} 77675 77676function createMapper(source) { 77677 var fill = source.fill; 77678 var type = 'dataset'; 77679 77680 if (fill === false) { 77681 return null; 77682 } 77683 77684 if (!isFinite(fill)) { 77685 type = 'boundary'; 77686 } 77687 77688 return mappers[type](source); 77689} 77690 77691function isDrawable(point) { 77692 return point && !point.skip; 77693} 77694 77695function drawArea(ctx, curve0, curve1, len0, len1) { 77696 var i; 77697 77698 if (!len0 || !len1) { 77699 return; 77700 } 77701 77702 // building first area curve (normal) 77703 ctx.moveTo(curve0[0].x, curve0[0].y); 77704 for (i = 1; i < len0; ++i) { 77705 helpers$1.canvas.lineTo(ctx, curve0[i - 1], curve0[i]); 77706 } 77707 77708 // joining the two area curves 77709 ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y); 77710 77711 // building opposite area curve (reverse) 77712 for (i = len1 - 1; i > 0; --i) { 77713 helpers$1.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true); 77714 } 77715} 77716 77717function doFill(ctx, points, mapper, view, color, loop) { 77718 var count = points.length; 77719 var span = view.spanGaps; 77720 var curve0 = []; 77721 var curve1 = []; 77722 var len0 = 0; 77723 var len1 = 0; 77724 var i, ilen, index, p0, p1, d0, d1; 77725 77726 ctx.beginPath(); 77727 77728 for (i = 0, ilen = (count + !!loop); i < ilen; ++i) { 77729 index = i % count; 77730 p0 = points[index]._view; 77731 p1 = mapper(p0, index, view); 77732 d0 = isDrawable(p0); 77733 d1 = isDrawable(p1); 77734 77735 if (d0 && d1) { 77736 len0 = curve0.push(p0); 77737 len1 = curve1.push(p1); 77738 } else if (len0 && len1) { 77739 if (!span) { 77740 drawArea(ctx, curve0, curve1, len0, len1); 77741 len0 = len1 = 0; 77742 curve0 = []; 77743 curve1 = []; 77744 } else { 77745 if (d0) { 77746 curve0.push(p0); 77747 } 77748 if (d1) { 77749 curve1.push(p1); 77750 } 77751 } 77752 } 77753 } 77754 77755 drawArea(ctx, curve0, curve1, len0, len1); 77756 77757 ctx.closePath(); 77758 ctx.fillStyle = color; 77759 ctx.fill(); 77760} 77761 77762var plugin_filler = { 77763 id: 'filler', 77764
77765 afterDatasetsUpdate: function(chart, options) { 77766 var count = (chart.data.datasets || []).length; 77767 var propagate = options.propagate; 77768 var sources = []; 77769 var meta, i, el, source; 77770 77771 for (i = 0; i < count; ++i) { 77772 meta = chart.getDatasetMeta(i); 77773 el = meta.dataset; 77774 source = null; 77775 77776 if (el && el._model && el instanceof elements.Line) { 77777 source = { 77778 visible: chart.isDatasetVisible(i), 77779 fill: decodeFill(el, i, count), 77780 chart: chart, 77781 el: el 77782 }; 77783 } 77784 77785 meta.$filler = source; 77786 sources.push(source); 77787 } 77788 77789 for (i = 0; i < count; ++i) { 77790 source = sources[i]; 77791 if (!source) { 77792 continue; 77793 } 77794 77795 source.fill = resolveTarget(sources, i, propagate); 77796 source.boundary = computeBoundary(source); 77797 source.mapper = createMapper(source); 77798 } 77799 }, 77800 77801 beforeDatasetDraw: function(chart, args) { 77802 var meta = args.meta.$filler; 77803 if (!meta) { 77804 return; 77805 } 77806 77807 var ctx = chart.ctx; 77808 var el = meta.el; 77809 var view = el._view; 77810 var points = el._children || []; 77811 var mapper = meta.mapper; 77812 var color = view.backgroundColor || core_defaults.global.defaultColor; 77813 77814 if (mapper && color && points.length) { 77815 helpers$1.canvas.clipArea(ctx, chart.chartArea); 77816 doFill(ctx, points, mapper, view, color, el._loop); 77817 helpers$1.canvas.unclipArea(ctx); 77818 } 77819 } 77820}; 77821 77822var noop$1 = helpers$1.noop; 77823var valueOrDefault$d = helpers$1.valueOrDefault; 77824 77825core_defaults._set('global', { 77826 legend: { 77827 display: true, 77828 position: 'top', 77829 fullWidth: true, 77830 reverse: false, 77831 weight: 1000, 77832 77833 // a callback that will handle 77834 onClick: function(e, legendItem) { 77835 var index = legendItem.datasetIndex; 77836 var ci = this.chart; 77837 var meta = ci.getDatasetMeta(index); 77838 77839 // See controller.isDatasetVisible comment 77840 meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null; 77841 77842 // We hid a dataset ... rerender the chart 77843 ci.update(); 77844 }, 77845 77846 onHover: null, 77847 onLeave: null, 77848 77849 labels: { 77850 boxWidth: 40, 77851 padding: 10, 77852 // Generates labels shown in the legend 77853 // Valid properties to return: 77854 // text : text to display 77855 // fillStyle : fill of coloured box 77856 // strokeStyle: stroke of coloured box 77857 // hidden : if this legend item refers to a hidden item 77858 // lineCap : cap style for line 77859 // lineDash 77860 // lineDashOffset : 77861 // lineJoin : 77862 // lineWidth : 77863 generateLabels: function(chart) { 77864 var data = chart.data; 77865 return helpers$1.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { 77866 return { 77867 text: dataset.label, 77868 fillStyle: (!helpers$1.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]), 77869 hidden: !chart.isDatasetVisible(i), 77870 lineCap: dataset.borderCapStyle, 77871 lineDash: dataset.borderDash, 77872 lineDashOffset: dataset.borderDashOffset, 77873 lineJoin: dataset.borderJoinStyle, 77874 lineWidth: dataset.borderWidth, 77875 strokeStyle: dataset.borderColor, 77876 pointStyle: dataset.pointStyle, 77877 77878 // Below is extra data used for toggling the datasets 77879 datasetIndex: i 77880 }; 77881 }, this) : []; 77882 } 77883 } 77884 }, 77885 77886 legendCallback: function(chart) { 77887 var text = []; 77888 text.push('<ul class="' + chart.id + '-legend">'); 77889 for (var i = 0; i < chart.data.datasets.length; i++) { 77890 text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>'); 77891 if (chart.data.datasets[i].label) { 77892 text.push(chart.data.datasets[i].label); 77893 } 77894 text.push('</li>'); 77895 } 77896 text.push('</ul>'); 77897 return text.join(''); 77898 } 77899}); 77900 77901/** 77902 * Helper function to get the box width based on the usePointStyle option 77903 * @param {object} labelopts - the label options on the legend 77904 * @param {number} fontSize - the label font size 77905 * @return {number} width of the color box area 77906 */ 77907function getBoxWidth(labelOpts, fontSize) { 77908 return labelOpts.usePointStyle && labelOpts.boxWidth > fontSize ? 77909 fontSize : 77910 labelOpts.boxWidth; 77911} 77912 77913/** 77914 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required! 77915 */ 77916var Legend = core_element.extend({ 77917 77918 initialize: function(config) { 77919 helpers$1.extend(this, config); 77920 77921 // Contains hit boxes for each dataset (in dataset order) 77922 this.legendHitBoxes = []; 77923 77924 /** 77925 * @private 77926 */ 77927 this._hoveredItem = null; 77928 77929 // Are we in doughnut mode which has a different data type 77930 this.doughnutMode = false;
vendor: 20,223 bytes, lines 77931-78737
77931 }, 77932 77933 // These methods are ordered by lifecycle. Utilities then follow. 77934 // Any function defined here is inherited by all legend types. 77935 // Any function can be extended by the legend type 77936 77937 beforeUpdate: noop$1, 77938 update: function(maxWidth, maxHeight, margins) { 77939 var me = this; 77940 77941 // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) 77942 me.beforeUpdate(); 77943 77944 // Absorb the master measurements 77945 me.maxWidth = maxWidth; 77946 me.maxHeight = maxHeight; 77947 me.margins = margins; 77948 77949 // Dimensions 77950 me.beforeSetDimensions(); 77951 me.setDimensions(); 77952 me.afterSetDimensions(); 77953 // Labels 77954 me.beforeBuildLabels(); 77955 me.buildLabels(); 77956 me.afterBuildLabels(); 77957 77958 // Fit 77959 me.beforeFit(); 77960 me.fit(); 77961 me.afterFit(); 77962 // 77963 me.afterUpdate(); 77964 77965 return me.minSize; 77966 }, 77967 afterUpdate: noop$1, 77968 77969 // 77970 77971 beforeSetDimensions: noop$1, 77972 setDimensions: function() { 77973 var me = this; 77974 // Set the unconstrained dimension before label rotation 77975 if (me.isHorizontal()) { 77976 // Reset position before calculating rotation 77977 me.width = me.maxWidth; 77978 me.left = 0; 77979 me.right = me.width; 77980 } else { 77981 me.height = me.maxHeight; 77982 77983 // Reset position before calculating rotation 77984 me.top = 0; 77985 me.bottom = me.height; 77986 } 77987 77988 // Reset padding 77989 me.paddingLeft = 0; 77990 me.paddingTop = 0; 77991 me.paddingRight = 0; 77992 me.paddingBottom = 0; 77993 77994 // Reset minSize 77995 me.minSize = { 77996 width: 0, 77997 height: 0 77998 }; 77999 }, 78000 afterSetDimensions: noop$1, 78001 78002 // 78003 78004 beforeBuildLabels: noop$1, 78005 buildLabels: function() { 78006 var me = this; 78007 var labelOpts = me.options.labels || {}; 78008 var legendItems = helpers$1.callback(labelOpts.generateLabels, [me.chart], me) || []; 78009 78010 if (labelOpts.filter) { 78011 legendItems = legendItems.filter(function(item) { 78012 return labelOpts.filter(item, me.chart.data); 78013 }); 78014 } 78015 78016 if (me.options.reverse) { 78017 legendItems.reverse(); 78018 } 78019 78020 me.legendItems = legendItems; 78021 }, 78022 afterBuildLabels: noop$1, 78023 78024 // 78025 78026 beforeFit: noop$1, 78027 fit: function() { 78028 var me = this; 78029 var opts = me.options; 78030 var labelOpts = opts.labels; 78031 var display = opts.display; 78032 78033 var ctx = me.ctx; 78034 78035 var labelFont = helpers$1.options._parseFont(labelOpts); 78036 var fontSize = labelFont.size; 78037 78038 // Reset hit boxes 78039 var hitboxes = me.legendHitBoxes = []; 78040 78041 var minSize = me.minSize; 78042 var isHorizontal = me.isHorizontal(); 78043 78044 if (isHorizontal) { 78045 minSize.width = me.maxWidth; // fill all the width 78046 minSize.height = display ? 10 : 0; 78047 } else { 78048 minSize.width = display ? 10 : 0; 78049 minSize.height = me.maxHeight; // fill all the height 78050 } 78051 78052 // Increase sizes here 78053 if (display) { 78054 ctx.font = labelFont.string; 78055 78056 if (isHorizontal) { 78057 // Labels 78058 78059 // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one 78060 var lineWidths = me.lineWidths = [0]; 78061 var totalHeight = 0; 78062 78063 ctx.textAlign = 'left'; 78064 ctx.textBaseline = 'top'; 78065 78066 helpers$1.each(me.legendItems, function(legendItem, i) { 78067 var boxWidth = getBoxWidth(labelOpts, fontSize); 78068 var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; 78069 78070 if (i === 0 || lineWidths[lineWidths.length - 1] + width + labelOpts.padding > minSize.width) { 78071 totalHeight += fontSize + labelOpts.padding; 78072 lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = labelOpts.padding; 78073 } 78074 78075 // Store the hitbox width and height here. Final position will be updated in `draw` 78076 hitboxes[i] = { 78077 left: 0, 78078 top: 0, 78079 width: width, 78080 height: fontSize 78081 }; 78082 78083 lineWidths[lineWidths.length - 1] += width + labelOpts.padding; 78084 }); 78085 78086 minSize.height += totalHeight; 78087 78088 } else { 78089 var vPadding = labelOpts.padding; 78090 var columnWidths = me.columnWidths = []; 78091 var totalWidth = labelOpts.padding; 78092 var currentColWidth = 0; 78093 var currentColHeight = 0; 78094 var itemHeight = fontSize + vPadding; 78095 78096 helpers$1.each(me.legendItems, function(legendItem, i) { 78097 var boxWidth = getBoxWidth(labelOpts, fontSize); 78098 var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; 78099 78100 // If too tall, go to new column 78101 if (i > 0 && currentColHeight + itemHeight > minSize.height - vPadding) { 78102 totalWidth += currentColWidth + labelOpts.padding; 78103 columnWidths.push(currentColWidth); // previous column width 78104 78105 currentColWidth = 0; 78106 currentColHeight = 0; 78107 } 78108 78109 // Get max width 78110 currentColWidth = Math.max(currentColWidth, itemWidth); 78111 currentColHeight += itemHeight; 78112 78113 // Store the hitbox width and height here. Final position will be updated in `draw` 78114 hitboxes[i] = { 78115 left: 0, 78116 top: 0, 78117 width: itemWidth, 78118 height: fontSize 78119 }; 78120 }); 78121 78122 totalWidth += currentColWidth; 78123 columnWidths.push(currentColWidth); 78124 minSize.width += totalWidth; 78125 } 78126 } 78127 78128 me.width = minSize.width; 78129 me.height = minSize.height; 78130 }, 78131 afterFit: noop$1, 78132 78133 // Shared Methods 78134 isHorizontal: function() { 78135 return this.options.position === 'top' || this.options.position === 'bottom'; 78136 }, 78137 78138 // Actually draw the legend on the canvas 78139 draw: function() { 78140 var me = this; 78141 var opts = me.options; 78142 var labelOpts = opts.labels; 78143 var globalDefaults = core_defaults.global; 78144 var defaultColor = globalDefaults.defaultColor; 78145 var lineDefault = globalDefaults.elements.line; 78146 var legendWidth = me.width; 78147 var lineWidths = me.lineWidths; 78148 78149 if (opts.display) { 78150 var ctx = me.ctx; 78151 var fontColor = valueOrDefault$d(labelOpts.fontColor, globalDefaults.defaultFontColor); 78152 var labelFont = helpers$1.options._parseFont(labelOpts); 78153 var fontSize = labelFont.size; 78154 var cursor; 78155 78156 // Canvas setup 78157 ctx.textAlign = 'left'; 78158 ctx.textBaseline = 'middle'; 78159 ctx.lineWidth = 0.5; 78160 ctx.strokeStyle = fontColor; // for strikethrough effect 78161 ctx.fillStyle = fontColor; // render in correct colour 78162 ctx.font = labelFont.string; 78163 78164 var boxWidth = getBoxWidth(labelOpts, fontSize); 78165 var hitboxes = me.legendHitBoxes; 78166 78167 // current position 78168 var drawLegendBox = function(x, y, legendItem) { 78169 if (isNaN(boxWidth) || boxWidth <= 0) { 78170 return; 78171 } 78172 78173 // Set the ctx for the box 78174 ctx.save(); 78175 78176 var lineWidth = valueOrDefault$d(legendItem.lineWidth, lineDefault.borderWidth); 78177 ctx.fillStyle = valueOrDefault$d(legendItem.fillStyle, defaultColor); 78178 ctx.lineCap = valueOrDefault$d(legendItem.lineCap, lineDefault.borderCapStyle); 78179 ctx.lineDashOffset = valueOrDefault$d(legendItem.lineDashOffset, lineDefault.borderDashOffset); 78180 ctx.lineJoin = valueOrDefault$d(legendItem.lineJoin, lineDefault.borderJoinStyle); 78181 ctx.lineWidth = lineWidth; 78182 ctx.strokeStyle = valueOrDefault$d(legendItem.strokeStyle, defaultColor); 78183 78184 if (ctx.setLineDash) { 78185 // IE 9 and 10 do not support line dash 78186 ctx.setLineDash(valueOrDefault$d(legendItem.lineDash, lineDefault.borderDash)); 78187 } 78188 78189 if (opts.labels && opts.labels.usePointStyle) { 78190 // Recalculate x and y for drawPoint() because its expecting 78191 // x and y to be center of figure (instead of top left) 78192 var radius = boxWidth * Math.SQRT2 / 2; 78193 var centerX = x + boxWidth / 2; 78194 var centerY = y + fontSize / 2; 78195 78196 // Draw pointStyle as legend symbol 78197 helpers$1.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); 78198 } else { 78199 // Draw box as legend symbol 78200 if (lineWidth !== 0) { 78201 ctx.strokeRect(x, y, boxWidth, fontSize); 78202 } 78203 ctx.fillRect(x, y, boxWidth, fontSize); 78204 } 78205 78206 ctx.restore(); 78207 }; 78208 var fillText = function(x, y, legendItem, textWidth) { 78209 var halfFontSize = fontSize / 2; 78210 var xLeft = boxWidth + halfFontSize + x; 78211 var yMiddle = y + halfFontSize; 78212 78213 ctx.fillText(legendItem.text, xLeft, yMiddle); 78214 78215 if (legendItem.hidden) { 78216 // Strikethrough the text if hidden 78217 ctx.beginPath(); 78218 ctx.lineWidth = 2; 78219 ctx.moveTo(xLeft, yMiddle); 78220 ctx.lineTo(xLeft + textWidth, yMiddle); 78221 ctx.stroke(); 78222 } 78223 }; 78224 78225 // Horizontal 78226 var isHorizontal = me.isHorizontal(); 78227 if (isHorizontal) { 78228 cursor = { 78229 x: me.left + ((legendWidth - lineWidths[0]) / 2) + labelOpts.padding, 78230 y: me.top + labelOpts.padding, 78231 line: 0 78232 }; 78233 } else { 78234 cursor = { 78235 x: me.left + labelOpts.padding, 78236 y: me.top + labelOpts.padding, 78237 line: 0 78238 }; 78239 } 78240 78241 var itemHeight = fontSize + labelOpts.padding; 78242 helpers$1.each(me.legendItems, function(legendItem, i) { 78243 var textWidth = ctx.measureText(legendItem.text).width; 78244 var width = boxWidth + (fontSize / 2) + textWidth; 78245 var x = cursor.x; 78246 var y = cursor.y; 78247 78248 // Use (me.left + me.minSize.width) and (me.top + me.minSize.height) 78249 // instead of me.right and me.bottom because me.width and me.height 78250 // may have been changed since me.minSize was calculated 78251 if (isHorizontal) { 78252 if (i > 0 && x + width + labelOpts.padding > me.left + me.minSize.width) { 78253 y = cursor.y += itemHeight; 78254 cursor.line++; 78255 x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2) + labelOpts.padding; 78256 } 78257 } else if (i > 0 && y + itemHeight > me.top + me.minSize.height) { 78258 x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding; 78259 y = cursor.y = me.top + labelOpts.padding; 78260 cursor.line++; 78261 } 78262 78263 drawLegendBox(x, y, legendItem); 78264 78265 hitboxes[i].left = x; 78266 hitboxes[i].top = y; 78267 78268 // Fill the actual label 78269 fillText(x, y, legendItem, textWidth); 78270 78271 if (isHorizontal) { 78272 cursor.x += width + labelOpts.padding; 78273 } else { 78274 cursor.y += itemHeight; 78275 } 78276 78277 }); 78278 } 78279 }, 78280 78281 /** 78282 * @private 78283 */ 78284 _getLegendItemAt: function(x, y) { 78285 var me = this; 78286 var i, hitBox, lh; 78287 78288 if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { 78289 // See if we are touching one of the dataset boxes 78290 lh = me.legendHitBoxes; 78291 for (i = 0; i < lh.length; ++i) { 78292 hitBox = lh[i]; 78293 78294 if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { 78295 // Touching an element 78296 return me.legendItems[i]; 78297 } 78298 } 78299 } 78300 78301 return null; 78302 }, 78303 78304 /** 78305 * Handle an event 78306 * @private 78307 * @param {IEvent} event - The event to handle 78308 */ 78309 handleEvent: function(e) { 78310 var me = this; 78311 var opts = me.options; 78312 var type = e.type === 'mouseup' ? 'click' : e.type; 78313 var hoveredItem; 78314 78315 if (type === 'mousemove') { 78316 if (!opts.onHover && !opts.onLeave) { 78317 return; 78318 } 78319 } else if (type === 'click') { 78320 if (!opts.onClick) { 78321 return; 78322 } 78323 } else { 78324 return; 78325 } 78326 78327 // Chart event already has relative position in it 78328 hoveredItem = me._getLegendItemAt(e.x, e.y); 78329 78330 if (type === 'click') { 78331 if (hoveredItem && opts.onClick) { 78332 // use e.native for backwards compatibility 78333 opts.onClick.call(me, e.native, hoveredItem); 78334 } 78335 } else { 78336 if (opts.onLeave && hoveredItem !== me._hoveredItem) { 78337 if (me._hoveredItem) { 78338 opts.onLeave.call(me, e.native, me._hoveredItem); 78339 } 78340 me._hoveredItem = hoveredItem; 78341 } 78342 78343 if (opts.onHover && hoveredItem) { 78344 // use e.native for backwards compatibility 78345 opts.onHover.call(me, e.native, hoveredItem); 78346 } 78347 } 78348 } 78349}); 78350 78351function createNewLegendAndAttach(chart, legendOpts) { 78352 var legend = new Legend({ 78353 ctx: chart.ctx, 78354 options: legendOpts, 78355 chart: chart 78356 }); 78357 78358 core_layouts.configure(chart, legend, legendOpts); 78359 core_layouts.addBox(chart, legend); 78360 chart.legend = legend; 78361} 78362 78363var plugin_legend = { 78364 id: 'legend', 78365 78366 /** 78367 * Backward compatibility: since 2.1.5, the legend is registered as a plugin, making 78368 * Chart.Legend obsolete. To avoid a breaking change, we export the Legend as part of 78369 * the plugin, which one will be re-exposed in the chart.js file. 78370 * https://github.com/chartjs/Chart.js/pull/2640 78371 * @private 78372 */ 78373 _element: Legend, 78374 78375 beforeInit: function(chart) { 78376 var legendOpts = chart.options.legend; 78377 78378 if (legendOpts) { 78379 createNewLegendAndAttach(chart, legendOpts); 78380 } 78381 }, 78382 78383 beforeUpdate: function(chart) { 78384 var legendOpts = chart.options.legend; 78385 var legend = chart.legend; 78386 78387 if (legendOpts) { 78388 helpers$1.mergeIf(legendOpts, core_defaults.global.legend); 78389 78390 if (legend) { 78391 core_layouts.configure(chart, legend, legendOpts); 78392 legend.options = legendOpts; 78393 } else { 78394 createNewLegendAndAttach(chart, legendOpts); 78395 } 78396 } else if (legend) { 78397 core_layouts.removeBox(chart, legend); 78398 delete chart.legend; 78399 } 78400 }, 78401 78402 afterEvent: function(chart, e) { 78403 var legend = chart.legend; 78404 if (legend) { 78405 legend.handleEvent(e); 78406 } 78407 } 78408}; 78409 78410var noop$2 = helpers$1.noop; 78411 78412core_defaults._set('global', { 78413 title: { 78414 display: false, 78415 fontStyle: 'bold', 78416 fullWidth: true, 78417 padding: 10, 78418 position: 'top', 78419 text: '', 78420 weight: 2000 // by default greater than legend (1000) to be above 78421 } 78422}); 78423 78424/** 78425 * IMPORTANT: this class is exposed publicly as Chart.Legend, backward compatibility required! 78426 */ 78427var Title = core_element.extend({ 78428 initialize: function(config) { 78429 var me = this; 78430 helpers$1.extend(me, config); 78431 78432 // Contains hit boxes for each dataset (in dataset order) 78433 me.legendHitBoxes = []; 78434 }, 78435 78436 // These methods are ordered by lifecycle. Utilities then follow. 78437 78438 beforeUpdate: noop$2, 78439 update: function(maxWidth, maxHeight, margins) { 78440 var me = this; 78441 78442 // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) 78443 me.beforeUpdate(); 78444 78445 // Absorb the master measurements 78446 me.maxWidth = maxWidth; 78447 me.maxHeight = maxHeight; 78448 me.margins = margins; 78449 78450 // Dimensions 78451 me.beforeSetDimensions(); 78452 me.setDimensions(); 78453 me.afterSetDimensions(); 78454 // Labels 78455 me.beforeBuildLabels(); 78456 me.buildLabels(); 78457 me.afterBuildLabels(); 78458 78459 // Fit 78460 me.beforeFit(); 78461 me.fit(); 78462 me.afterFit(); 78463 // 78464 me.afterUpdate(); 78465 78466 return me.minSize; 78467 78468 }, 78469 afterUpdate: noop$2, 78470 78471 // 78472 78473 beforeSetDimensions: noop$2, 78474 setDimensions: function() { 78475 var me = this; 78476 // Set the unconstrained dimension before label rotation 78477 if (me.isHorizontal()) { 78478 // Reset position before calculating rotation 78479 me.width = me.maxWidth; 78480 me.left = 0; 78481 me.right = me.width; 78482 } else { 78483 me.height = me.maxHeight; 78484 78485 // Reset position before calculating rotation 78486 me.top = 0; 78487 me.bottom = me.height; 78488 } 78489 78490 // Reset padding 78491 me.paddingLeft = 0; 78492 me.paddingTop = 0; 78493 me.paddingRight = 0; 78494 me.paddingBottom = 0; 78495 78496 // Reset minSize 78497 me.minSize = { 78498 width: 0, 78499 height: 0 78500 }; 78501 }, 78502 afterSetDimensions: noop$2, 78503 78504 // 78505 78506 beforeBuildLabels: noop$2, 78507 buildLabels: noop$2, 78508 afterBuildLabels: noop$2, 78509 78510 // 78511 78512 beforeFit: noop$2, 78513 fit: function() { 78514 var me = this; 78515 var opts = me.options; 78516 var display = opts.display; 78517 var minSize = me.minSize; 78518 var lineCount = helpers$1.isArray(opts.text) ? opts.text.length : 1; 78519 var fontOpts = helpers$1.options._parseFont(opts); 78520 var textSize = display ? (lineCount * fontOpts.lineHeight) + (opts.padding * 2) : 0; 78521 78522 if (me.isHorizontal()) { 78523 minSize.width = me.maxWidth; // fill all the width 78524 minSize.height = textSize; 78525 } else { 78526 minSize.width = textSize; 78527 minSize.height = me.maxHeight; // fill all the height 78528 } 78529 78530 me.width = minSize.width; 78531 me.height = minSize.height; 78532 78533 }, 78534 afterFit: noop$2, 78535 78536 // Shared Methods 78537 isHorizontal: function() { 78538 var pos = this.options.position; 78539 return pos === 'top' || pos === 'bottom'; 78540 }, 78541 78542 // Actually draw the title block on the canvas 78543 draw: function() { 78544 var me = this; 78545 var ctx = me.ctx; 78546 var opts = me.options; 78547 78548 if (opts.display) { 78549 var fontOpts = helpers$1.options._parseFont(opts); 78550 var lineHeight = fontOpts.lineHeight; 78551 var offset = lineHeight / 2 + opts.padding; 78552 var rotation = 0; 78553 var top = me.top; 78554 var left = me.left; 78555 var bottom = me.bottom; 78556 var right = me.right; 78557 var maxWidth, titleX, titleY; 78558 78559 ctx.fillStyle = helpers$1.valueOrDefault(opts.fontColor, core_defaults.global.defaultFontColor); // render in correct colour 78560 ctx.font = fontOpts.string; 78561 78562 // Horizontal 78563 if (me.isHorizontal()) { 78564 titleX = left + ((right - left) / 2); // midpoint of the width 78565 titleY = top + offset; 78566 maxWidth = right - left; 78567 } else { 78568 titleX = opts.position === 'left' ? left + offset : right - offset; 78569 titleY = top + ((bottom - top) / 2); 78570 maxWidth = bottom - top; 78571 rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5); 78572 } 78573 78574 ctx.save(); 78575 ctx.translate(titleX, titleY); 78576 ctx.rotate(rotation); 78577 ctx.textAlign = 'center'; 78578 ctx.textBaseline = 'middle'; 78579 78580 var text = opts.text; 78581 if (helpers$1.isArray(text)) { 78582 var y = 0; 78583 for (var i = 0; i < text.length; ++i) { 78584 ctx.fillText(text[i], 0, y, maxWidth); 78585 y += lineHeight; 78586 } 78587 } else { 78588 ctx.fillText(text, 0, 0, maxWidth); 78589 } 78590 78591 ctx.restore(); 78592 } 78593 } 78594}); 78595 78596function createNewTitleBlockAndAttach(chart, titleOpts) { 78597 var title = new Title({ 78598 ctx: chart.ctx, 78599 options: titleOpts, 78600 chart: chart 78601 }); 78602 78603 core_layouts.configure(chart, title, titleOpts); 78604 core_layouts.addBox(chart, title); 78605 chart.titleBlock = title; 78606} 78607 78608var plugin_title = { 78609 id: 'title', 78610 78611 /** 78612 * Backward compatibility: since 2.1.5, the title is registered as a plugin, making 78613 * Chart.Title obsolete. To avoid a breaking change, we export the Title as part of 78614 * the plugin, which one will be re-exposed in the chart.js file. 78615 * https://github.com/chartjs/Chart.js/pull/2640 78616 * @private 78617 */ 78618 _element: Title, 78619 78620 beforeInit: function(chart) { 78621 var titleOpts = chart.options.title; 78622 78623 if (titleOpts) { 78624 createNewTitleBlockAndAttach(chart, titleOpts); 78625 } 78626 }, 78627 78628 beforeUpdate: function(chart) { 78629 var titleOpts = chart.options.title; 78630 var titleBlock = chart.titleBlock; 78631 78632 if (titleOpts) { 78633 helpers$1.mergeIf(titleOpts, core_defaults.global.title); 78634 78635 if (titleBlock) { 78636 core_layouts.configure(chart, titleBlock, titleOpts); 78637 titleBlock.options = titleOpts; 78638 } else { 78639 createNewTitleBlockAndAttach(chart, titleOpts); 78640 } 78641 } else if (titleBlock) { 78642 core_layouts.removeBox(chart, titleBlock); 78643 delete chart.titleBlock; 78644 } 78645 } 78646}; 78647 78648var plugins = {}; 78649var filler = plugin_filler; 78650var legend = plugin_legend; 78651var title = plugin_title; 78652plugins.filler = filler; 78653plugins.legend = legend; 78654plugins.title = title; 78655 78656/** 78657 * @namespace Chart 78658 */ 78659 78660 78661core_controller.helpers = helpers$1; 78662 78663// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests! 78664core_helpers(core_controller); 78665 78666core_controller._adapters = core_adapters; 78667core_controller.Animation = core_animation; 78668core_controller.animationService = core_animations; 78669core_controller.controllers = controllers; 78670core_controller.DatasetController = core_datasetController; 78671core_controller.defaults = core_defaults; 78672core_controller.Element = core_element; 78673core_controller.elements = elements; 78674core_controller.Interaction = core_interaction; 78675core_controller.layouts = core_layouts; 78676core_controller.platform = platform; 78677core_controller.plugins = core_plugins; 78678core_controller.Scale = core_scale; 78679core_controller.scaleService = core_scaleService; 78680core_controller.Ticks = core_ticks; 78681core_controller.Tooltip = core_tooltip; 78682 78683// Register built-in scales 78684 78685core_controller.helpers.each(scales, function(scale, type) { 78686 core_controller.scaleService.registerScaleType(type, scale, scale._defaults); 78687}); 78688 78689// Load to register built-in adapters (as side effects) 78690 78691 78692// Loading built-in plugins 78693 78694for (var k in plugins) { 78695 if (plugins.hasOwnProperty(k)) { 78696 core_controller.plugins.register(plugins[k]); 78697 } 78698} 78699 78700core_controller.platform.initialize(); 78701 78702var src = core_controller; 78703if (typeof window !== 'undefined') { 78704 window.Chart = core_controller; 78705} 78706 78707// DEPRECATIONS 78708 78709/** 78710 * Provided for backward compatibility, not available anymore 78711 * @namespace Chart.Chart 78712 * @deprecated since version 2.8.0 78713 * @todo remove at version 3 78714 * @private 78715 */ 78716core_controller.Chart = core_controller; 78717 78718/** 78719 * Provided for backward compatibility, not available anymore 78720 * @namespace Chart.Legend 78721 * @deprecated since version 2.1.5 78722 * @todo remove at version 3 78723 * @private 78724 */ 78725core_controller.Legend = plugins.legend._element; 78726 78727/** 78728 * Provided for backward compatibility, not available anymore 78729 * @namespace Chart.Title 78730 * @deprecated since version 2.1.5 78731 * @todo remove at version 3 78732 * @private 78733 */ 78734core_controller.Title = plugins.title._element; 78735 78736/** 78737 * Provided for backward compatibility, use Chart.plugins instead
78738 * @namespace Chart.pluginService 78739 * @deprecated since version 2.1.5 78740 * @todo remove at version 3 78741 * @private 78742 */ 78743core_controller.pluginService = core_controller.plugins; 78744 78745/** 78746 * Provided for backward compatibility, inheriting from Chart.PlugingBase has no 78747 * effect, instead simply create/register plugins via plain JavaScript objects. 78748 * @interface Chart.PluginBase 78749 * @deprecated since version 2.5.0 78750 * @todo remove at version 3 78751 * @private 78752 */ 78753core_controller.PluginBase = core_controller.Element.extend({}); 78754 78755/** 78756 * Provided for backward compatibility, use Chart.helpers.canvas instead. 78757 * @namespace Chart.canvasHelpers 78758 * @deprecated since version 2.6.0 78759 * @todo remove at version 3 78760 * @private 78761 */ 78762core_controller.canvasHelpers = core_controller.helpers.canvas; 78763 78764/** 78765 * Provided for backward compatibility, use Chart.layouts instead. 78766 * @namespace Chart.layoutService 78767 * @deprecated since version 2.7.3 78768 * @todo remove at version 3 78769 * @private 78770 */ 78771core_controller.layoutService = core_controller.layouts; 78772 78773/** 78774 * Provided for backward compatibility, not available anymore. 78775 * @namespace Chart.LinearScaleBase 78776 * @deprecated since version 2.8 78777 * @todo remove at version 3 78778 * @private 78779 */ 78780core_controller.LinearScaleBase = scale_linearbase; 78781 78782/** 78783 * Provided for backward compatibility, instead we should create a new Chart 78784 * by setting the type in the config (`new Chart(id, {type: '{chart-type}'}`). 78785 * @deprecated since version 2.8.0 78786 * @todo remove at version 3 78787 */ 78788core_controller.helpers.each( 78789 [ 78790 'Bar', 78791 'Bubble', 78792 'Doughnut', 78793 'Line', 78794 'PolarArea', 78795 'Radar', 78796 'Scatter' 78797 ], 78798 function(klass) { 78799 core_controller[klass] = function(ctx, cfg) { 78800 return new core_controller(ctx, core_controller.helpers.merge(cfg || {}, { 78801 type: klass.charAt(0).toLowerCase() + klass.slice(1) 78802 })); 78803 }; 78804 } 78805); 78806 78807return src; 78808 78809}))); 78810 78811!function(a){"use strict";a.sessionTimeout=function(b){function c(){n||(a.ajax({type:i.ajaxType,url:i.keepAliveUrl,data:i.ajaxData}),n=!0,setTimeout(function(){n=!1},i.keepAliveInterval))}function d(){clearTimeout(g),(i.countdownMessage||i.countdownBar)&&f("session",!0),"function"==typeof i.onStart&&i.onStart(i),i.keepAlive&&c(),g=setTimeout(function(){"function"!=typeof i.onWarn?a("#session-timeout-dialog").modal("show"):i.onWarn(i),e()},i.warnAfter)}function e(){clearTimeout(g),a("#session-timeout-dialog").hasClass("in")||!i.countdownMessage&&!i.countdownBar||f("dialog",!0),g=setTimeout(function(){"function"!=typeof i.onRedir?window.location=i.redirUrl:i.onRedir(i)},i.redirAfter-i.warnAfter)}function f(b,c){clearTimeout(j.timer),"dialog"===b&&c?j.timeLeft=Math.floor((i.redirAfter-i.warnAfter)/1e3):"session"===b&&c&&(j.timeLeft=Math.floor(i.redirAfter/1e3)),i.countdownBar&&"dialog"===b?j.percentLeft=Math.floor(j.timeLeft/((i.redirAfter-i.warnAfter)/1e3)*100):i.countdownBar&&"session"===b&&(j.percentLeft=Math.floor(j.timeLeft/(i.redirAfter/1e3)*100));var d=a(".countdown-holder"),e=j.timeLeft>=0?j.timeLeft:0;if(i.countdownSmart){var g=Math.floor(e/60),h=e%60,k=g>0?g+"m":"";k.length>0&&(k+=" "),k+=h+"s",d.text(k)}else d.text(e+"s");i.countdownBar&&a(".countdown-bar").css("width",j.percentLeft+"%"),j.timeLeft=j.timeLeft-1,j.timer=setTimeout(function(){f(b)},1e3)}var g,h={title:"Your Session is About to Expire!",message:"Your session is about to expire.",logoutButton:"Logout",keepAliveButton:"Stay Connected",keepAliveUrl:"/keep-alive",ajaxType:"POST",ajaxData:"",redirUrl:"/timed-out",logoutUrl:"/log-out",warnAfter:9e5,redirAfter:12e5,keepAliveInterval:5e3,keepAlive:!0,ignoreUserActivity:!1,onStart:!1,onWarn:!1,onRedir:!1,countdownMessage:!1,countdownBar:!1,countdownSmart:!1},i=h,j={};if(b&&(i=a.extend(h,b)),i.warnAfter>=i.redirAfter)return console.error('Bootstrap-session-timeout plugin is miss-configured. Option "redirAfter" must be equal or greater than "warnAfter".'),!1;if("function"!=typeof i.onWarn){var k=i.countdownMessage?"<p>"+i.countdownMessage.replace(/{timer}/g,'<span class="countdown-holder"></span>')+"</p>":"",l=i.countdownBar?'<div class="progress"> <div class="progress-bar progress-bar-striped countdown-bar active" role="progressbar" style="min-width: 15px; width: 100%;">
78811 <span class="countdown-holder"></span> </div> </div>':"";a("body").append('<div class="modal fade" id="session-timeout-dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title">'+i.title+'</h4> </div> <div class="modal-body"> <p>'+i.message+"</p> "+k+" "+l+' </div> <div class="modal-footer"> <button id="session-timeout-dialog-logout" type="button" class="btn btn-default">'+i.logoutButton+'</button> <button id="session-timeout-dialog-keepalive" type="button" class="btn btn-primary" data-dismiss="modal">'+i.keepAliveButton+"</button> </div> </div> </div> </div>"),a("#session-timeout-dialog-logout").on("click",function(){window.location=i.logoutUrl}),a("#session-timeout-dialog").on("hide.bs.modal",function(){d()})}if(!i.ignoreUserActivity){var m=[-1,-1];a(document).on("keyup mouseup mousemove touchend touchmove",function(b){if("mousemove"===b.type){if(b.clientX===m[0]&&b.clientY===m[1])return;m[0]=b.clientX,m[1]=b.clientY}d(),a("#session-timeout-dialog").length>0&&a("#session-timeout-dialog").data("bs.modal")&&a("#session-timeout-dialog").data("bs.modal").isShown&&(a("#session-timeout-dialog").modal("hide"),a("body").removeClass("modal-open"),a("div.modal-backdrop").remove())})}var n=!1;d()}}(jQuery); 78812/*! Idle Timer v1.1.0 2016-03-21 | https://github.com/thorst/jquery-idletimer | (c) 2016 Paul Irish | Licensed MIT */ 78813!function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(("storage"!==b.type||b.originalEvent.key===d.timerSyncId)&&null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,"storage"!==b.type&&d.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(d.timerSyncId,d.lastActive),d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),d.timerSyncId&&a(window).bind("storage",h),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,timerSyncId:d.timerSyncId,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery); 78814/*! 78815Waypoints - 4.0.1 78816Copyright © 2011-2016 Caleb Troughton 78817Licensed under the MIT license. 78818https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 78819*/ 78820(function() { 78821 'use strict' 78822 78823 var keyCounter = 0 78824 var allWaypoints = {} 78825 78826 /* http://imakewebthings.com/waypoints/api/waypoint */ 78827 function Waypoint(options) { 78828 if (!options) { 78829 throw new Error('No options passed to Waypoint constructor') 78830 } 78831 if (!options.element) { 78832 throw new Error('No element option passed to Waypoint constructor') 78833 } 78834 if (!options.handler) { 78835 throw new Error('No handler option passed to Waypoint constructor') 78836 } 78837 78838 this.key = 'waypoint-' + keyCounter 78839 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 78840 this.element = this.options.element 78841 this.adapter = new Waypoint.Adapter(this.element) 78842 this.callback = options.handler 78843 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 78844 this.enabled = this.options.enabled 78845 this.triggerPoint = null 78846 this.group = Waypoint.Group.findOrCreate({ 78847 name: this.options.group, 78848 axis: this.axis 78849 }) 78850 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 78851 78852 if (Waypoint.offsetAliases[this.options.offset]) { 78853 this.options.offset = Waypoint.offsetAliases[this.options.offset] 78854 } 78855 this.group.add(this) 78856 this.context.add(this) 78857 allWaypoints[this.key] = this 78858 keyCounter += 1 78859 } 78860 78861 /* Private */ 78862 Waypoint.prototype.queueTrigger = function(direction) { 78863 this.group.queueTrigger(this, direction) 78864 } 78865 78866 /* Private */ 78867 Waypoint.prototype.trigger = function(args) { 78868 if (!this.enabled) { 78869 return 78870 } 78871 if (this.callback) { 78872 this.callback.apply(this, args) 78873 } 78874 } 78875 78876 /* Public */ 78877 /* http://imakewebthings.com/waypoints/api/destroy */ 78878 Waypoint.prototype.destroy = function() { 78879 this.context.remove(this) 78880 this.group.remove(this) 78881 delete allWaypoints[this.key] 78882 } 78883 78884 /* Public */ 78885 /* http://imakewebthings.com/waypoints/api/disable */ 78886 Waypoint.prototype.disable = function() { 78887 this.enabled = false 78888 return this 78889 } 78890 78891 /* Public */ 78892 /* http://imakewebthings.com/waypoints/api/enable */ 78893 Waypoint.prototype.enable = function() { 78894 this.context.refresh() 78895 this.enabled = true 78896 return this 78897 } 78898 78899 /* Public */ 78900 /* http://imakewebthings.com/waypoints/api/next */ 78901 Waypoint.prototype.next = function() { 78902 return this.group.next(this) 78903 } 78904 78905 /* Public */ 78906 /* http://imakewebthings.com/waypoints/api/previous */ 78907 Waypoint.prototype.previous = function() { 78908 return this.group.previous(this) 78909 } 78910 78911 /* Private */ 78912 Waypoint.invokeAll = function(method) { 78913 var allWaypointsArray = []
78914 for (var waypointKey in allWaypoints) { 78915 allWaypointsArray.push(allWaypoints[waypointKey]) 78916 } 78917 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 78918 allWaypointsArray[i][method]() 78919 } 78920 } 78921 78922 /* Public */ 78923 /* http://imakewebthings.com/waypoints/api/destroy-all */ 78924 Waypoint.destroyAll = function() { 78925 Waypoint.invokeAll('destroy') 78926 } 78927 78928 /* Public */ 78929 /* http://imakewebthings.com/waypoints/api/disable-all */ 78930 Waypoint.disableAll = function() { 78931 Waypoint.invokeAll('disable') 78932 } 78933 78934 /* Public */ 78935 /* http://imakewebthings.com/waypoints/api/enable-all */ 78936 Waypoint.enableAll = function() { 78937 Waypoint.Context.refreshAll() 78938 for (var waypointKey in allWaypoints) { 78939 allWaypoints[waypointKey].enabled = true 78940 } 78941 return this 78942 } 78943 78944 /* Public */ 78945 /* http://imakewebthings.com/waypoints/api/refresh-all */ 78946 Waypoint.refreshAll = function() { 78947 Waypoint.Context.refreshAll() 78948 } 78949 78950 /* Public */ 78951 /* http://imakewebthings.com/waypoints/api/viewport-height */ 78952 Waypoint.viewportHeight = function() { 78953 return window.innerHeight || document.documentElement.clientHeight 78954 } 78955 78956 /* Public */ 78957 /* http://imakewebthings.com/waypoints/api/viewport-width */ 78958 Waypoint.viewportWidth = function() { 78959 return document.documentElement.clientWidth 78960 } 78961 78962 Waypoint.adapters = [] 78963 78964 Waypoint.defaults = { 78965 context: window, 78966 continuous: true, 78967 enabled: true, 78968 group: 'default', 78969 horizontal: false, 78970 offset: 0 78971 } 78972 78973 Waypoint.offsetAliases = { 78974 'bottom-in-view': function() { 78975 return this.context.innerHeight() - this.adapter.outerHeight() 78976 }, 78977 'right-in-view': function() { 78978 return this.context.innerWidth() - this.adapter.outerWidth() 78979 } 78980 } 78981 78982 window.Waypoint = Waypoint 78983}()) 78984;(function() { 78985 'use strict' 78986 78987 function requestAnimationFrameShim(callback) { 78988 window.setTimeout(callback, 1000 / 60) 78989 } 78990 78991 var keyCounter = 0 78992 var contexts = {} 78993 var Waypoint = window.Waypoint 78994 var oldWindowLoad = window.onload 78995 78996 /* http://imakewebthings.com/waypoints/api/context */ 78997 function Context(element) { 78998 this.element = element 78999 this.Adapter = Waypoint.Adapter 79000 this.adapter = new this.Adapter(element) 79001 this.key = 'waypoint-context-' + keyCounter 79002 this.didScroll = false 79003 this.didResize = false 79004 this.oldScroll = { 79005 x: this.adapter.scrollLeft(), 79006 y: this.adapter.scrollTop() 79007 } 79008 this.waypoints = { 79009 vertical: {}, 79010 horizontal: {} 79011 } 79012 79013 element.waypointContextKey = this.key 79014 contexts[element.waypointContextKey] = this 79015 keyCounter += 1 79016 if (!Waypoint.windowContext) { 79017 Waypoint.windowContext = true 79018 Waypoint.windowContext = new Context(window) 79019 } 79020 79021 this.createThrottledScrollHandler() 79022 this.createThrottledResizeHandler() 79023 } 79024 79025 /* Private */ 79026 Context.prototype.add = function(waypoint) { 79027 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 79028 this.waypoints[axis][waypoint.key] = waypoint 79029 this.refresh() 79030 } 79031 79032 /* Private */ 79033 Context.prototype.checkEmpty = function() { 79034 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 79035 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 79036 var isWindow = this.element == this.element.window 79037 if (horizontalEmpty && verticalEmpty && !isWindow) { 79038 this.adapter.off('.waypoints') 79039 delete contexts[this.key] 79040 } 79041 } 79042 79043 /* Private */ 79044 Context.prototype.createThrottledResizeHandler = function() { 79045 var self = this 79046 79047 function resizeHandler() { 79048 self.handleResize() 79049 self.didResize = false 79050 } 79051 79052 this.adapter.on('resize.waypoints', function() { 79053 if (!self.didResize) { 79054 self.didResize = true 79055 Waypoint.requestAnimationFrame(resizeHandler) 79056 } 79057 }) 79058 } 79059 79060 /* Private */ 79061 Context.prototype.createThrottledScrollHandler = function() { 79062 var self = this 79063 function scrollHandler() { 79064 self.handleScroll() 79065 self.didScroll = false 79066 } 79067 79068 this.adapter.on('scroll.waypoints', function() { 79069 if (!self.didScroll || Waypoint.isTouch) { 79070 self.didScroll = true 79071 Waypoint.requestAnimationFrame(scrollHandler) 79072 } 79073 }) 79074 } 79075 79076 /* Private */ 79077 Context.prototype.handleResize = function() { 79078 Waypoint.Context.refreshAll() 79079 } 79080 79081 /* Private */ 79082 Context.prototype.handleScroll = function() { 79083 var triggeredGroups = {} 79084 var axes = { 79085 horizontal: { 79086 newScroll: this.adapter.scrollLeft(), 79087 oldScroll: this.oldScroll.x, 79088 forward: 'right', 79089 backward: 'left' 79090 }, 79091 vertical: { 79092 newScroll: this.adapter.scrollTop(), 79093 oldScroll: this.oldScroll.y, 79094 forward: 'down', 79095 backward: 'up' 79096 } 79097 } 79098 79099 for (var axisKey in axes) { 79100 var axis = axes[axisKey] 79101 var isForward = axis.newScroll > axis.oldScroll 79102 var direction = isForward ? axis.forward : axis.backward 79103
79104 for (var waypointKey in this.waypoints[axisKey]) { 79105 var waypoint = this.waypoints[axisKey][waypointKey] 79106 if (waypoint.triggerPoint === null) { 79107 continue 79108 } 79109 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 79110 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 79111 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 79112 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 79113 if (crossedForward || crossedBackward) { 79114 waypoint.queueTrigger(direction) 79115 triggeredGroups[waypoint.group.id] = waypoint.group 79116 } 79117 } 79118 } 79119 79120 for (var groupKey in triggeredGroups) { 79121 triggeredGroups[groupKey].flushTriggers() 79122 } 79123 79124 this.oldScroll = { 79125 x: axes.horizontal.newScroll, 79126 y: axes.vertical.newScroll 79127 } 79128 } 79129 79130 /* Private */ 79131 Context.prototype.innerHeight = function() { 79132 /*eslint-disable eqeqeq */ 79133 if (this.element == this.element.window) { 79134 return Waypoint.viewportHeight() 79135 } 79136 /*eslint-enable eqeqeq */ 79137 return this.adapter.innerHeight() 79138 } 79139 79140 /* Private */ 79141 Context.prototype.remove = function(waypoint) { 79142 delete this.waypoints[waypoint.axis][waypoint.key] 79143 this.checkEmpty() 79144 } 79145 79146 /* Private */ 79147 Context.prototype.innerWidth = function() { 79148 /*eslint-disable eqeqeq */ 79149 if (this.element == this.element.window) { 79150 return Waypoint.viewportWidth() 79151 } 79152 /*eslint-enable eqeqeq */ 79153 return this.adapter.innerWidth() 79154 } 79155 79156 /* Public */ 79157 /* http://imakewebthings.com/waypoints/api/context-destroy */ 79158 Context.prototype.destroy = function() { 79159 var allWaypoints = [] 79160 for (var axis in this.waypoints) {
79161 for (var waypointKey in this.waypoints[axis]) { 79162 allWaypoints.push(this.waypoints[axis][waypointKey]) 79163 } 79164 } 79165 for (var i = 0, end = allWaypoints.length; i < end; i++) { 79166 allWaypoints[i].destroy() 79167 } 79168 } 79169 79170 /* Public */ 79171 /* http://imakewebthings.com/waypoints/api/context-refresh */ 79172 Context.prototype.refresh = function() { 79173 /*eslint-disable eqeqeq */ 79174 var isWindow = this.element == this.element.window 79175 /*eslint-enable eqeqeq */ 79176 var contextOffset = isWindow ? undefined : this.adapter.offset() 79177 var triggeredGroups = {} 79178 var axes 79179 79180 this.handleScroll() 79181 axes = { 79182 horizontal: { 79183 contextOffset: isWindow ? 0 : contextOffset.left, 79184 contextScroll: isWindow ? 0 : this.oldScroll.x, 79185 contextDimension: this.innerWidth(), 79186 oldScroll: this.oldScroll.x, 79187 forward: 'right', 79188 backward: 'left', 79189 offsetProp: 'left' 79190 }, 79191 vertical: { 79192 contextOffset: isWindow ? 0 : contextOffset.top, 79193 contextScroll: isWindow ? 0 : this.oldScroll.y, 79194 contextDimension: this.innerHeight(), 79195 oldScroll: this.oldScroll.y, 79196 forward: 'down', 79197 backward: 'up', 79198 offsetProp: 'top' 79199 } 79200 } 79201 79202 for (var axisKey in axes) { 79203 var axis = axes[axisKey]
79204 for (var waypointKey in this.waypoints[axisKey]) { 79205 var waypoint = this.waypoints[axisKey][waypointKey] 79206 var adjustment = waypoint.options.offset 79207 var oldTriggerPoint = waypoint.triggerPoint 79208 var elementOffset = 0 79209 var freshWaypoint = oldTriggerPoint == null 79210 var contextModifier, wasBeforeScroll, nowAfterScroll 79211 var triggeredBackward, triggeredForward 79212 79213 if (waypoint.element !== waypoint.element.window) { 79214 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 79215 } 79216 79217 if (typeof adjustment === 'function') { 79218 adjustment = adjustment.apply(waypoint) 79219 } 79220 else if (typeof adjustment === 'string') { 79221 adjustment = parseFloat(adjustment) 79222 if (waypoint.options.offset.indexOf('%') > - 1) { 79223 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 79224 } 79225 } 79226 79227 contextModifier = axis.contextScroll - axis.contextOffset 79228 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 79229 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 79230 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 79231 triggeredBackward = wasBeforeScroll && nowAfterScroll 79232 triggeredForward = !wasBeforeScroll && !nowAfterScroll 79233 79234 if (!freshWaypoint && triggeredBackward) { 79235 waypoint.queueTrigger(axis.backward) 79236 triggeredGroups[waypoint.group.id] = waypoint.group 79237 } 79238 else if (!freshWaypoint && triggeredForward) { 79239 waypoint.queueTrigger(axis.forward) 79240 triggeredGroups[waypoint.group.id] = waypoint.group 79241 } 79242 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 79243 waypoint.queueTrigger(axis.forward) 79244 triggeredGroups[waypoint.group.id] = waypoint.group 79245 } 79246 } 79247 } 79248 79249 Waypoint.requestAnimationFrame(function() { 79250 for (var groupKey in triggeredGroups) { 79251 triggeredGroups[groupKey].flushTriggers() 79252 } 79253 }) 79254 79255 return this 79256 } 79257 79258 /* Private */ 79259 Context.findOrCreateByElement = function(element) { 79260 return Context.findByElement(element) || new Context(element) 79261 } 79262 79263 /* Private */ 79264 Context.refreshAll = function() { 79265 for (var contextId in contexts) { 79266 contexts[contextId].refresh() 79267 } 79268 } 79269 79270 /* Public */ 79271 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 79272 Context.findByElement = function(element) { 79273 return contexts[element.waypointContextKey] 79274 } 79275 79276 window.onload = function() { 79277 if (oldWindowLoad) { 79278 oldWindowLoad() 79279 } 79280 Context.refreshAll() 79281 } 79282 79283 79284 Waypoint.requestAnimationFrame = function(callback) { 79285 var requestFn = window.requestAnimationFrame || 79286 window.mozRequestAnimationFrame || 79287 window.webkitRequestAnimationFrame || 79288 requestAnimationFrameShim 79289 requestFn.call(window, callback) 79290 } 79291 Waypoint.Context = Context 79292}()) 79293;(function() { 79294 'use strict' 79295 79296 function byTriggerPoint(a, b) { 79297 return a.triggerPoint - b.triggerPoint 79298 } 79299 79300 function byReverseTriggerPoint(a, b) { 79301 return b.triggerPoint - a.triggerPoint 79302 } 79303 79304 var groups = { 79305 vertical: {}, 79306 horizontal: {} 79307 } 79308 var Waypoint = window.Waypoint 79309 79310 /* http://imakewebthings.com/waypoints/api/group */ 79311 function Group(options) { 79312 this.name = options.name 79313 this.axis = options.axis 79314 this.id = this.name + '-' + this.axis 79315 this.waypoints = [] 79316 this.clearTriggerQueues() 79317 groups[this.axis][this.name] = this 79318 } 79319 79320 /* Private */ 79321 Group.prototype.add = function(waypoint) { 79322 this.waypoints.push(waypoint) 79323 } 79324 79325 /* Private */ 79326 Group.prototype.clearTriggerQueues = function() { 79327 this.triggerQueues = { 79328 up: [], 79329 down: [], 79330 left: [], 79331 right: [] 79332 } 79333 } 79334 79335 /* Private */ 79336 Group.prototype.flushTriggers = function() { 79337 for (var direction in this.triggerQueues) { 79338 var waypoints = this.triggerQueues[direction] 79339 var reverse = direction === 'up' || direction === 'left' 79340 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 79341 for (var i = 0, end = waypoints.length; i < end; i += 1) { 79342 var waypoint = waypoints[i] 79343 if (waypoint.options.continuous || i === waypoints.length - 1) { 79344 waypoint.trigger([direction]) 79345 } 79346 } 79347 } 79348 this.clearTriggerQueues() 79349 } 79350 79351 /* Private */ 79352 Group.prototype.next = function(waypoint) { 79353 this.waypoints.sort(byTriggerPoint) 79354 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 79355 var isLast = index === this.waypoints.length - 1 79356 return isLast ? null : this.waypoints[index + 1] 79357 } 79358 79359 /* Private */ 79360 Group.prototype.previous = function(waypoint) { 79361 this.waypoints.sort(byTriggerPoint) 79362 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 79363 return index ? this.waypoints[index - 1] : null 79364 } 79365 79366 /* Private */ 79367 Group.prototype.queueTrigger = function(waypoint, direction) { 79368 this.triggerQueues[direction].push(waypoint) 79369 } 79370 79371 /* Private */ 79372 Group.prototype.remove = function(waypoint) { 79373 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 79374 if (index > -1) { 79375 this.waypoints.splice(index, 1) 79376 } 79377 } 79378 79379 /* Public */ 79380 /* http://imakewebthings.com/waypoints/api/first */ 79381 Group.prototype.first = function() { 79382 return this.waypoints[0] 79383 } 79384 79385 /* Public */ 79386 /* http://imakewebthings.com/waypoints/api/last */ 79387 Group.prototype.last = function() { 79388 return this.waypoints[this.waypoints.length - 1] 79389 } 79390 79391 /* Private */ 79392 Group.findOrCreate = function(options) { 79393 return groups[options.axis][options.name] || new Group(options) 79394 } 79395 79396 Waypoint.Group = Group 79397}()) 79398;(function() { 79399 'use strict' 79400 79401 var $ = window.jQuery 79402 var Waypoint = window.Waypoint 79403 79404 function JQueryAdapter(element) { 79405 this.$element = $(element) 79406 } 79407 79408 $.each([
79409 'innerHeight', 79410 'innerWidth', 79411 'off', 79412 'offset', 79413 'on', 79414 'outerHeight', 79415 'outerWidth', 79416 'scrollLeft', 79417 'scrollTop' 79418 ], function(i, method) { 79419 JQueryAdapter.prototype[method] = function() { 79420 var args = Array.prototype.slice.call(arguments) 79421 return this.$element[method].apply(this.$element, args) 79422 } 79423 }) 79424 79425 $.each([ 79426 'extend', 79427 'inArray', 79428 'isEmptyObject' 79429 ], function(i, method) { 79430 JQueryAdapter[method] = $[method] 79431 }) 79432 79433 Waypoint.adapters.push({ 79434 name: 'jquery', 79435 Adapter: JQueryAdapter 79436 }) 79437 Waypoint.Adapter = JQueryAdapter 79438}()) 79439;(function() { 79440 'use strict' 79441 79442 var Waypoint = window.Waypoint 79443 79444 function createExtension(framework) { 79445 return function() { 79446 var waypoints = [] 79447 var overrides = arguments[0] 79448 79449 if (framework.isFunction(arguments[0])) { 79450 overrides = framework.extend({}, arguments[1]) 79451 overrides.handler = arguments[0] 79452 } 79453 79454 this.each(function() { 79455 var options = framework.extend({}, overrides, { 79456 element: this 79457 }) 79458 if (typeof options.context === 'string') { 79459 options.context = framework(this).closest(options.context)[0] 79460 } 79461 waypoints.push(new Waypoint(options)) 79462 }) 79463 79464 return waypoints 79465 } 79466 } 79467 79468 if (window.jQuery) { 79469 window.jQuery.fn.waypoint = createExtension(window.jQuery) 79470 } 79471 if (window.Zepto) { 79472 window.Zepto.fn.waypoint = createExtension(window.Zepto) 79473 } 79474}()) 79475; 79476/*! 79477* jquery.counterup.js 1.0 79478* 79479* Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 79480* Released under the GPL v2 License 79481* 79482* Date: Nov 26, 2013 79483*/ 79484!function(t){"use strict";t.fn.counterUp=function(e){var u=t.extend({time:400,delay:10},e);return this.each(function(){var e=t(this),n=u,a=function(){var t=n.time/n.delay,u=e.attr("data-value"),a=[u],r=/[0-9]+,[0-9]+/.test(u);u=u.replace(/,/g,"");for(var o=(/^[0-9]+$/.test(u),/^[0-9]+\.[0-9]+$/.test(u)),c=o?(u.split(".")[1]||[]).length:0,d=t;d>=1;d--){var s=parseInt(u/t*d);if(o&&(s=parseFloat(u/t*d).toFixed(c)),r)for(;/(\d+)(\d{3})/.test(s.toString());)s=s.toString().replace(/(\d+)(\d{3})/,"$1,$2");a.unshift(s)}e.data("counterup-nums",a),e.text("0");var i=function(){e.data("counterup-nums")&&(e.text(e.data("counterup-nums").shift()),e.data("counterup-nums").length?setTimeout(e.data("counterup-func"),n.delay):(delete e.data("counterup-nums"),e.data("counterup-nums",null),e.data("counterup-func",null)))};e.data("counterup-func",i),setTimeout(e.data("counterup-func"),n.delay)};e.waypoint(a,{offset:"100%",triggerOnce:!0})})}}(jQuery); 79485 79486(function(t){function z(){for(var a=0;a<g.length;a++)g[a][0](g[a][1]);g=[];m=!1}function n(a,b){g.push([a,b]);m||(m=!0,A(z,0))}function B(a,b){function c(a){p(b,a)}function h(a){k(b,a)}try{a(c,h)}catch(d){h(d)}}function u(a){var b=a.owner,c=b.state_,b=b.data_,h=a[c];a=a.then;if("function"===typeof h){c=l;try{b=h(b)}catch(d){k(a,d)}}v(a,b)||(c===l&&p(a,b),c===q&&k(a,b))}function v(a,b){var c;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(b&&("function"=== 79487typeof b||"object"===typeof b)){var h=b.then;if("function"===typeof h)return h.call(b,function(d){c||(c=!0,b!==d?p(a,d):w(a,d))},function(b){c||(c=!0,k(a,b))}),!0}}catch(d){return c||k(a,d),!0}return!1}function p(a,b){a!==b&&v(a,b)||w(a,b)}function w(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(C,a))}function k(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(D,a))}function y(a){var b=a.then_;a.then_=void 0;for(a=0;a<b.length;a++)u(b[a])}function C(a){a.state_=l;y(a)}function D(a){a.state_=q;y(a)}function e(a){if("function"!== 79488typeof a)throw new TypeError("Promise constructor takes a function argument");if(!1===this instanceof e)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object c
79488onstructor cannot be called as a function.");this.then_=[];B(a,this)}var f=t.Promise,s=f&&"resolve"in f&&"reject"in f&&"all"in f&&"race"in f&&function(){var a;new f(function(b){a=b});return"function"===typeof a}();"undefined"!==typeof exports&&exports?(exports.Promise=s?f:e,exports.Polyfill=e):"function"== 79489typeof define&&define.amd?define(function(){return s?f:e}):s||(t.Promise=e);var r="pending",x="sealed",l="fulfilled",q="rejected",E=function(){},A="undefined"!==typeof setImmediate?setImmediate:setTimeout,g=[],m;e.prototype={constructor:e,state_:r,then_:null,data_:void 0,then:function(a,b){var c={owner:this,then:new this.constructor(E),fulfilled:a,rejected:b};this.state_===l||this.state_===q?n(u,c):this.then_.push(c);return c.then},"catch":function(a){return this.then(null,a)}};e.all=function(a){if("[object Array]"!== 79490Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.all().");return new this(function(b,c){function h(a){e++;return function(c){d[a]=c;--e||b(d)}}for(var d=[],e=0,f=0,g;f<a.length;f++)(g=a[f])&&"function"===typeof g.then?g.then(h(f),c):d[f]=g;e||b(d)})};e.race=function(a){if("[object Array]"!==Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.race().");return new this(function(b,c){for(var e=0,d;e<a.length;e++)(d=a[e])&&"function"=== 79491typeof d.then?d.then(b,c):b(d)})};e.resolve=function(a){return a&&"object"===typeof a&&a.constructor===this?a:new this(function(b){b(a)})};e.reject=function(a){return new this(function(b,c){c(a)})}})("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this); 79492 79493!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Sweetalert2=t()}(this,function(){"use strict";function q(e){return(q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function i(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}function r(){return(r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e}).apply(this,arguments)}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&u(e,t)}function c(e){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){return(u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function l(e,t,n){return(l=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,n){var o=[null];o.push.apply(o,t);var i=new(Function.bind.apply(e,o));return n&&u(i,n.prototype),i}).apply(null,arguments)}function d(e,t){return!t||"object"!=typeof t&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function p(e,t,n){return(p="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(e,t,n){var o=function(e,t){for(;!Object.prototype.hasOwnProperty.call(e,t)&&null!==(e=c(e)););return e}(e,t);if(o){var i=Object.getOwnPropertyDescriptor(o,t);return i.get?i.get.call(n):i.value}})(e,t,n||e)}var t="SweetAlert2:",f=function(e){return Array.prototype.slice.call(e)},R=function(e){console.warn("".concat(t," ").concat(e))},I=function(e){console.error("".concat(t," ").concat(e))},n=[],m=function(e){-1===n.indexOf(e)&&(n.push(e),R(e))},H=function(e){return"function"==typeof e?e():e},D=function(e){return e&&Promise.resolve(e)===e},e=Object.freeze({cancel:"cancel",backdrop:"overlay",close:"close",esc:"esc",timer:"timer"}),h=function(e){var t={};for(var n in e)t[e[n]]="swal2-"+e[n];return t},_=h(["container","shown","height-auto","iosfix","popup","modal","no-backdrop","toast","toast-shown","toast-column","fade","show","hide","noanimation","close","title","header","content","actions","confirm","cancel","footer","icon","icon-text","image","input","file","range","select","radio","checkbox","label","textarea","inputerror","validation-message","progresssteps","activeprogressstep","progresscircle","progressline","loading","styled","top","top-start","to
79493p-end","top-left","top-right","center","center-start","center-end","center-left","center-right","bottom","bottom-start","bottom-end","bottom-left","bottom-right","grow-row","grow-column","grow-fullscreen","rtl"]),g=h(["success","warning","info","question","error"]),b={previousBodyPadding:null},v=function(e,t){return e.classList.contains(t)},N=function(e){if(e.focus(),"file"!==e.type){var t=e.value;e.value="",e.value=t}},y=function(e,t,n){e&&t&&("string"==typeof t&&(t=t.split(/\s+/).filter(Boolean)),t.forEach(function(t){e.forEach?e.forEach(function(e){n?e.classList.add(t):e.classList.remove(t)}):n?e.classList.add(t):e.classList.remove(t)}))},z=function(e,t){y(e,t,!0)},W=function(e,t){y(e,t,!1)},U=function(e,t){for(var n=0;n<e.childNodes.length;n++)if(v(e.childNodes[n],t))return e.childNodes[n]},K=function(e){e.style.opacity="",e.style.display=e.id===_.content?"block":"flex"},F=function(e){e.style.opacity="",e.style.display="none"},Z=function(e){return e&&(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w=function(){return document.body.querySelector("."+_.container)},C=function(e){var t=w();return t?t.querySelector("."+e):null},k=function(){return C(_.popup)},x=function(){var e=k();return f(e.querySelectorAll("."+_.icon))},A=function(){return C(_.title)},B=function(){return C(_.content)},S=function(){return C(_.image)},P=function(){return C(_.progresssteps)},E=function(){return C(_["validation-message"])},L=function(){return C(_.confirm)},O=function(){return C(_.cancel)},Q=function(){return C(_.actions)},Y=function(){return C(_.footer)},$=function(){return C(_.close)},J=function(){var e=f(k().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')).sort(function(e,t){return e=parseInt(e.getAttribute("tabindex")),(t=parseInt(t.getAttribute("tabindex")))<e?1:e<t?-1:0}),t=f(k().querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable], audio[controls], video[controls]')).filter(function(e){return"-1"!==e.getAttribute("tabindex")});return function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}(e.concat(t)).filter(function(e){return Z(e)})},T=function(){return!M()&&!document.body.classList.contains(_["no-backdrop"])},M=function(){return document.body.classList.contains(_["toast-shown"])},j=function(){return"undefined"==typeof window||"undefined"==typeof document},V='\n <div aria-labelledby="'.concat(_.title,'" aria-describedby="').concat(_.content,'" class="').concat(_.popup,'" tabindex="-1">\n <div class="').concat(_.header,'">\n <ul class="').concat(_.progresssteps,'"></ul>\n <div class="').concat(_.icon," ").concat(g.error,'">\n <span class="swal2-x-mark"><span class="swal2-x-mark-line-left"></span><span class="swal2-x-mark-line-right"></span></span>\n </div>\n <div class="').concat(_.icon," ").concat(g.question,'">\n <span class="').concat(_["icon-text"],'">?</span>\n </div>\n <div class="').concat(_.icon," ").concat(g.warning,'">\n <span class="').concat(_["icon-text"],'">!</span>\n </div>\n <div class="').concat(_.icon," ").concat(g.info,'">\n <span class="').concat(_["icon-text"],'">i</span>\n </div>\n <div class="').concat(_.icon," ").concat(g.success,'">\n <div class="swal2-success-circular-line-left"></div>\n <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>\n <div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>\n <div class="swal2-success-circular-line-right"></div>\n </div>\n <img class="').concat(_.image,'" />\n <h2 class="').concat(_.title,'" id="').concat(_.title,'"></h2>\n <button type="button" class="').concat(_.close,'">Ã</button>\n </div>\n <div class="').concat(_.content,'">\n <div id="').concat(_.content,'"></div>\n <input class="').concat(_.input,'" />\n <input type="file" class="').concat(_.file,'" />\n <div class="').concat(_.range,'">\n <input type="range" />\n <output></output>\n </div>\n <select class="').concat(_.select,'"></select>\n <div class="').concat(_.radio,'"></div>
79493\n <label for="').concat(_.checkbox,'" class="').concat(_.checkbox,'">\n <input type="checkbox" />\n <span class="').concat(_.label,'"></span>\n </label>\n <textarea class="').concat(_.textarea,'"></textarea>\n <div class="').concat(_["validation-message"],'" id="').concat(_["validation-message"],'"></div>\n </div>\n <div class="').concat(_.actions,'">\n <button type="button" class="').concat(_.confirm,'">OK</button>\n <button type="button" class="').concat(_.cancel,'">Cancel</button>\n </div>\n <div class="').concat(_.footer,'">\n </div>\n </div>\n').replace(/(^|\n)\s*/g,""),X=function(e){var t=w();if(t&&(t.parentNode.removeChild(t),W([document.documentElement,document.body],[_["no-backdrop"],_["toast-shown"],_["has-column"]])),!j()){var n=document.createElement("div");n.className=_.container,n.innerHTML=V;var o="string"==typeof e.target?document.querySelector(e.target):e.target;o.appendChild(n);var i,r=k(),a=B(),s=U(a,_.input),c=U(a,_.file),u=a.querySelector(".".concat(_.range," input")),l=a.querySelector(".".concat(_.range," output")),d=U(a,_.select),p=a.querySelector(".".concat(_.checkbox," input")),f=U(a,_.textarea);r.setAttribute("role",e.toast?"alert":"dialog"),r.setAttribute("aria-live",e.toast?"polite":"assertive"),e.toast||r.setAttribute("aria-modal","true"),"rtl"===window.getComputedStyle(o).direction&&z(w(),_.rtl);var m=function(e){De.isVisible()&&i!==e.target.value&&De.resetValidationMessage(),i=e.target.value};return s.oninput=m,c.onchange=m,d.onchange=m,p.onchange=m,f.oninput=m,u.oninput=function(e){m(e),l.value=u.value},u.onchange=function(e){m(e),u.nextSibling.value=u.value},r}I("SweetAlert2 requires document to initialize")},G=function(e,t){if(!e)return F(t);if(e instanceof HTMLElement)t.appendChild(e);else if("object"===q(e))if(t.innerHTML="",0 in e)for(var n=0;n in e;n++)t.appendChild(e[n].cloneNode(!0));else t.appendChild(e.cloneNode(!0));else e&&(t.innerHTML=e);K(t)},ee=function(){if(j())return!1;var e=document.createElement("div"),t={WebkitAnimation:"webkitAnimationEnd",OAnimation:"oAnimationEnd oanimationend",animation:"animationend"};for(var n in t)if(t.hasOwnProperty(n)&&void 0!==e.style[n])return t[n];return!1}(),te=function(e){var t=Q(),n=L(),o=O();if(e.showConfirmButton||e.showCancelButton?K(t):F(t),e.showCancelButton?o.style.display="inline-block":F(o),e.showConfirmButton?n.style.removeProperty("display"):F(n),n.innerHTML=e.confirmButtonText,o.innerHTML=e.cancelButtonText,n.setAttribute("aria-label",e.confirmButtonAriaLabel),o.setAttribute("aria-label",e.cancelButtonAriaLabel),n.className=_.confirm,z(n,e.confirmButtonClass),o.className=_.cancel,z(o,e.cancelButtonClass),e.buttonsStyling){z([n,o],_.styled),e.confirmButtonColor&&(n.style.backgroundColor=e.confirmButtonColor),e.cancelButtonColor&&(o.style.backgroundColor=e.cancelButtonColor);var i=window.getComputedStyle(n).getPropertyValue("background-color");n.style.borderLeftColor=i,n.style.borderRightColor=i}else W([n,o],_.styled),n.style.backgroundColor=n.style.borderLeftColor=n.style.borderRightColor="",o.style.backgroundColor=o.style.borderLeftColor=o.style.borderRightColor=""},ne=function(e){var t=B().querySelector("#"+_.content);e.html?G(e.html,t):e.text?(t.textContent=e.text,K(t)):F(t)},oe=function(e){for(var t=x(),n=0;n<t.length;n++)F(t[n]);if(e.type)if(-1!==Object.keys(g).indexOf(e.type)){var o=De.getPopup().querySelector(".".concat(_.icon,".").concat(g[e.type]));K(o),e.animation&&z(o,"swal2-animate-".concat(e.type,"-icon"))}else I('Unknown type! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.type,'"'))},ie=function(e){var t=S();e.imageUrl?(t.setAttribute("src",e.imageUrl),t.setAttribute("alt",e.imageAlt),K(t),e.imageWidth?t.setAttribute("width",e.imageWidth):t.removeAttribute("width"),e.imageHeight?t.setAttribute("height",e.imageHeight):t.removeAttribute("height"),t.className=_.image,e.imageClass&&z(t,e.imageClass)):F(t)},re=function(i){var r=P(),a=parseInt(null===i.currentProgressStep?De.getQueueStep():i.currentProgressStep,10);i.progressSteps&&i.progressSteps.length?(K(r),r.innerHTML="",a>=i.progressSteps.length&&R("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),i.progressSteps.forEach(function(e,t){var n=document.createElement("li");if(z(n,_.progresscircle),n.innerHTML=e,t===a&&z(n,_.activeprogressstep),r.appendChild(n),t!==i.progressSteps.length-1){var o=document.createElement("li");z(o,_.progressline),i.progressStepsDistance&&(o.style.width=i.progressStepsDistance),r.appendChild(o)}})):F(r)},ae=function(e){var t=A();e.titleText?t.innerText=e.titleText:e.title&&("string"==typeof e.title&&(e.title=e.title.split("\n").join("<br />")),G(e.title,t))},se=function(){null===b.previousBodyPadding&&document.body.scrollHeight>window.innerHeight&&(b.previousBodyPadding=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight=b.previousBodyPadding+function(){if("ontouchstart"in window||navigator.msMaxTouchPoints)return 0;var e=document.createElement("div");
79493e.style.width="50px",e.style.height="50px",e.style.overflow="scroll",document.body.appendChild(e);var t=e.offsetWidth-e.clientWidth;return document.body.removeChild(e),t}()+"px")},ce=function(){return!!window.MSInputMethodContext&&!!document.documentMode},ue=function(){var e=w(),t=k();e.style.removeProperty("align-items"),t.offsetTop<0&&(e.style.alignItems="flex-start")},le={},de=function(e,t){var n=w(),o=k();if(o){null!==e&&"function"==typeof e&&e(o),W(o,_.show),z(o,_.hide);var i=function(){M()?pe(t):(new Promise(function(e){var t=window.scrollX,n=window.scrollY;le.restoreFocusTimeout=setTimeout(function(){le.previousActiveElement&&le.previousActiveElement.focus?(le.previousActiveElement.focus(),le.previousActiveElement=null):document.body&&document.body.focus(),e()},100),void 0!==t&&void 0!==n&&window.scrollTo(t,n)}).then(function(){return pe(t)}),le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),n.parentNode&&n.parentNode.removeChild(n),W([document.documentElement,document.body],[_.shown,_["height-auto"],_["no-backdrop"],_["toast-shown"],_["toast-column"]]),T()&&(null!==b.previousBodyPadding&&(document.body.style.paddingRight=b.previousBodyPadding,b.previousBodyPadding=null),function(){if(v(document.body,_.iosfix)){var e=parseInt(document.body.style.top,10);W(document.body,_.iosfix),document.body.style.top="",document.body.scrollTop=-1*e}}(),"undefined"!=typeof window&&ce()&&window.removeEventListener("resize",ue),f(document.body.children).forEach(function(e){e.hasAttribute("data-previous-aria-hidden")?(e.setAttribute("aria-hidden",e.getAttribute("data-previous-aria-hidden")),e.removeAttribute("data-previous-aria-hidden")):e.removeAttribute("aria-hidden")}))};ee&&!v(o,_.noanimation)?o.addEventListener(ee,function e(){o.removeEventListener(ee,e),v(o,_.hide)&&i()}):i()}},pe=function(e){null!==e&&"function"==typeof e&&setTimeout(function(){e()})};function fe(e){var t=function e(){for(var t=arguments.length,n=new Array(t),o=0;o<t;o++)n[o]=arguments[o];if(!(this instanceof e))return l(e,n);Object.getPrototypeOf(e).apply(this,n)};return t.prototype=r(Object.create(e.prototype),{constructor:t}),"function"==typeof Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e,t}var me={title:"",titleText:"",text:"",html:"",footer:"",type:null,toast:!1,customClass:"",customContainerClass:"",target:"body",backdrop:!0,animation:!0,heightAuto:!0,allowOutsideClick:!0,allowEscapeKey:!0,allowEnterKey:!0,stopKeydownPropagation:!0,keydownListenerCapture:!1,showConfirmButton:!0,showCancelButton:!1,preConfirm:null,confirmButtonText:"OK",confirmButtonAriaLabel:"",confirmButtonColor:null,confirmButtonClass:null,cancelButtonText:"Cancel",cancelButtonAriaLabel:"",cancelButtonColor:null,cancelButtonClass:null,buttonsStyling:!0,reverseButtons:!1,focusConfirm:!0,focusCancel:!1,showCloseButton:!1,closeButtonAriaLabel:"Close this dialog",showLoaderOnConfirm:!1,imageUrl:null,imageWidth:null,imageHeight:null,imageAlt:"",imageClass:null,timer:null,width:null,padding:null,background:null,input:null,inputPlaceholder:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputClass:null,inputAttributes:{},inputValidator:null,validationMessage:null,grow:!1,position:"center",progressSteps:[],currentProgressStep:null,progressStepsDistance:null,onBeforeOpen:null,onAfterClose:null,onOpen:null,onClose:null,useRejections:!1,expectRejections:!1},he=["useRejections","expectRejections","extraParams"],ge=["allowOutsideClick","allowEnterKey","backdrop","focusConfirm","focusCancel","heightAuto","keydownListenerCapture"],be=function(e){return me.hasOwnProperty(e)||"extraParams"===e},ve=function(e){return-1!==he.indexOf(e)},ye=function(e){for(var t in e)be(t)||R('Unknown parameter "'.concat(t,'"')),e.toast&&-1!==ge.indexOf(t)&&R('The parameter "'.concat(t,'" is incompatible with toasts')),ve(t)&&m('The parameter "'.concat(t,'" is deprecated and will be removed in the next major release.'))}
79493,we='"setDefaults" & "resetDefaults" methods are deprecated in favor of "mixin" method and will be removed in the next major release. For new projects, use "mixin". For past projects already using "setDefaults", support will be provided through an additional package.',Ce={};var ke=[],xe=function(){var e=k();e||De(""),e=k();var t=Q(),n=L(),o=O();K(t),K(n),z([e,t],_.loading),n.disabled=!0,o.disabled=!0,e.setAttribute("data-loading",!0),e.setAttribute("aria-busy",!0),e.focus()},Ae=Object.freeze({isValidParameter:be,isDeprecatedParameter:ve,argsToParams:function(n){var o={};switch(q(n[0])){case"object":r(o,n[0]);break;default:["title","html","type"].forEach(function(e,t){switch(q(n[t])){case"string":o[e]=n[t];break;case"undefined":break;default:I("Unexpected type of ".concat(e,'! Expected "string", got ').concat(q(n[t])))}})}return o},adaptInputValidator:function(n){return function(e,t){return n.call(this,e,t).then(function(){},function(e){return e})}},close:de,closePopup:de,closeModal:de,closeToast:de,isVisible:function(){return!!k()},clickConfirm:function(){return L().click()},clickCancel:function(){return O().click()},getContainer:w,getPopup:k,getTitle:A,getContent:B,getImage:S,getIcons:x,getCloseButton:$,getButtonsWrapper:function(){return m("swal.getButtonsWrapper() is deprecated and will be removed in the next major release, use swal.getActions() instead"),C(_.actions)},getActions:Q,getConfirmButton:L,getCancelButton:O,getFooter:Y,getFocusableElements:J,getValidationMessage:E,isLoading:function(){return k().hasAttribute("data-loading")},fire:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return l(this,t)},mixin:function(n){return fe(function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,e),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},n,e))}}]),t}(this))},queue:function(e){var r=this;ke=e;var a=function(){ke=[],document.body.removeAttribute("data-swal2-queue-step")},s=[];return new Promise(function(i){!function t(n,o){n<ke.length?(document.body.setAttribute("data-swal2-queue-step",n),r(ke[n]).then(function(e){void 0!==e.value?(s.push(e.value),t(n+1,o)):(a(),i({dismiss:e.dismiss}))})):(a(),i({value:s}))}(0)})},getQueueStep:function(){return document.body.getAttribute("data-swal2-queue-step")},insertQueueStep:function(e,t){return t&&t<ke.length?ke.splice(t,0,e):ke.push(e)},deleteQueueStep:function(e){void 0!==ke[e]&&ke.splice(e,1)},showLoading:xe,enableLoading:xe,getTimerLeft:function(){return le.timeout&&le.timeout.getTimerLeft()},stopTimer:function(){return le.timeout&&le.timeout.stop()},resumeTimer:function(){return le.timeout&&le.timeout.start()},toggleTimer:function(){var e=le.timeout;return e&&(e.running?e.stop():e.start())},increaseTimer:function(e){return le.timeout&&le.timeout.increase(e)},isTimerRunning:function(){return le.timeout&&le.timeout.isRunning()}}),Be="function"==typeof Symbol?Symbol:function(){var t=0;function e(e){return"__"+e+"_"+Math.floor(1e9*Math.random())+"_"+ ++t+"__"}return e.iterator=e("Symbol.iterator"),e}(),Se="function"==typeof WeakMap?WeakMap:function(n,o,t){function e(){o(this,n,{value:Be("WeakMap")})}return e.prototype={delete:function(e){delete e[this[n]]},get:function(e){return e[this[n]]},has:function(e){return t.call(e,this[n])},set:function(e,t){o(e,this[n],{configurable:!0,value:t})}},e}(Be("WeakMap"),Object.defineProperty,{}.hasOwnProperty),Pe={promise:new Se,innerParams:new Se,domCache:new Se};function Ee(){var e=Pe.innerParams.get(this),t=Pe.domCache.get(this);e.showConfirmButton||(F(t.confirmButton),e.showCancelButton||F(t.actions)),W([t.popup,t.actions],_.loading),t.popup.removeAttribute("aria-busy"),t.popup.removeAttribute("data-loading"),t.confirmButton.disabled=!1,t.cancelButton.disabled=!1}function Le(e){var t=Pe.domCache.get(this);t.validationMessage.innerHTML=e;var n=window.getComputedStyle(t.popup);t.validationMessage.style.marginLeft="-".concat(n.getPropertyValue("padding-left")),t.validationMessage.style.marginRight="-".concat(n.getPropertyValue("padding-right")),K(t.validationMessage);var o=this.getInput();o&&(o.setAttribute("aria-invalid",!0),o.setAttribute("aria-describedBy",_["validation-message"]),N(o),z(o,_.
79493inputerror))}function Oe(){var e=Pe.domCache.get(this);e.validationMessage&&F(e.validationMessage);var t=this.getInput();t&&(t.removeAttribute("aria-invalid"),t.removeAttribute("aria-describedBy"),W(t,_.inputerror))}var Te=function e(t,n){a(this,e);var o,i,r=n;this.running=!1,this.start=function(){return this.running||(this.running=!0,i=new Date,o=setTimeout(t,r)),r},this.stop=function(){return this.running&&(this.running=!1,clearTimeout(o),r-=new Date-i),r},this.increase=function(e){var t=this.running;return t&&this.stop(),r+=e,t&&this.start(),r},this.getTimerLeft=function(){return this.running&&(this.stop(),this.start()),r},this.isRunning=function(){return this.running},this.start()},Me={email:function(e,t){return/^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid email address")},url:function(e,t){return/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)$/.test(e)?Promise.resolve():Promise.reject(t&&t.validationMessage?t.validationMessage:"Invalid URL")}};var je=function(e){var t=w(),n=k();null!==e.onBeforeOpen&&"function"==typeof e.onBeforeOpen&&e.onBeforeOpen(n),e.animation?(z(n,_.show),z(t,_.fade),W(n,_.hide)):W(n,_.fade),K(n),t.style.overflowY="hidden",ee&&!v(n,_.noanimation)?n.addEventListener(ee,function e(){n.removeEventListener(ee,e),t.style.overflowY="auto"}):t.style.overflowY="auto",z([document.documentElement,document.body,t],_.shown),e.heightAuto&&e.backdrop&&!e.toast&&z([document.documentElement,document.body],_["height-auto"]),T()&&(se(),function(){if(/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream&&!v(document.body,_.iosfix)){var e=document.body.scrollTop;document.body.style.top=-1*e+"px",z(document.body,_.iosfix)}}(),"undefined"!=typeof window&&ce()&&(ue(),window.addEventListener("resize",ue)),f(document.body.children).forEach(function(e){e===w()||function(e,t){if("function"==typeof e.contains)return e.contains(t)}(e,w())||(e.hasAttribute("aria-hidden")&&e.setAttribute("data-previous-aria-hidden",e.getAttribute("aria-hidden")),e.setAttribute("aria-hidden","true"))}),setTimeout(function(){t.scrollTop=0})),M()||le.previousActiveElement||(le.previousActiveElement=document.activeElement),null!==e.onOpen&&"function"==typeof e.onOpen&&setTimeout(function(){e.onOpen(n)})};var Ve,qe=Object.freeze({hideLoading:Ee,disableLoading:Ee,getInput:function(e){var t=Pe.innerParams.get(this),n=Pe.domCache.get(this);if(!(e=e||t.input))return null;switch(e){case"select":case"textarea":case"file":return U(n.content,_[e]);case"checkbox":return n.popup.querySelector(".".concat(_.checkbox," input"));case"radio":return n.popup.querySelector(".".concat(_.radio," input:checked"))||n.popup.querySelector(".".concat(_.radio," input:first-child"));case"range":return n.popup.querySelector(".".concat(_.range," input"));default:return U(n.content,_.input)}},enableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!1,e.cancelButton.disabled=!1},disableButtons:function(){var e=Pe.domCache.get(this);e.confirmButton.disabled=!0,e.cancelButton.disabled=!0},enableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!1},disableConfirmButton:function(){Pe.domCache.get(this).confirmButton.disabled=!0},enableInput:function(){var e=this.getInput();if(!e)return!1;if("radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!1;else e.disabled=!1},disableInput:function(){var e=this.getInput();if(!e)return!1;if(e&&"radio"===e.type)for(var t=e.parentNode.parentNode.querySelectorAll("input"),n=0;n<t.length;n++)t[n].disabled=!0;else e.disabled=!0},showValidationMessage:Le,resetValidationMessage:Oe,resetValidationError:function(){m("Swal.resetValidationError() is deprecated and will be removed in the next major release, use Swal.resetValidationMessage() instead"),Oe.bind(this)()},showValidationError:function(e){m("Swal.showValidationError() is deprecated and will be removed in the next major release, use Swal.showValidationMessage() instead"),Le.bind(this)(e)},getProgressSteps:function(){return Pe.innerParams.get(this).progressSteps},setProgressSteps:function(e){var t=r({},Pe.innerParams.get(this),{progressSteps:e});Pe.innerParams.set(this,t),re(t)},showProgressSteps:function(){var e=Pe.domCache.get(this);K(e.progressSteps)},hideProgressSteps:function(){var e=Pe.domCache.get(this);F(e.progressSteps)},_main:function(e){var T=this;ye(e);var M=r({},me,e);!function(t){var e;
79493t.inputValidator||Object.keys(Me).forEach(function(e){t.input===e&&(t.inputValidator=t.expectRejections?Me[e]:De.adaptInputValidator(Me[e]))}),t.validationMessage&&("object"!==q(t.extraParams)&&(t.extraParams={}),t.extraParams.validationMessage=t.validationMessage),(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(R('Target parameter is not valid, defaulting to "body"'),t.target="body"),"function"==typeof t.animation&&(t.animation=t.animation.call());var n=k(),o="string"==typeof t.target?document.querySelector(t.target):t.target;e=n&&o&&n.parentNode!==o.parentNode?X(t):n||X(t),t.width&&(e.style.width="number"==typeof t.width?t.width+"px":t.width),t.padding&&(e.style.padding="number"==typeof t.padding?t.padding+"px":t.padding),t.background&&(e.style.background=t.background);for(var i=window.getComputedStyle(e).getPropertyValue("background-color"),r=e.querySelectorAll("[class^=swal2-success-circular-line], .swal2-success-fix"),a=0;a<r.length;a++)r[a].style.backgroundColor=i;var s=w(),c=$(),u=Y();if(ae(t),ne(t),"string"==typeof t.backdrop?w().style.background=t.backdrop:t.backdrop||z([document.documentElement,document.body],_["no-backdrop"]),!t.backdrop&&t.allowOutsideClick&&R('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'),t.position in _?z(s,_[t.position]):(R('The "position" parameter is not valid, defaulting to "center"'),z(s,_.center)),t.grow&&"string"==typeof t.grow){var l="grow-"+t.grow;l in _&&z(s,_[l])}t.showCloseButton?(c.setAttribute("aria-label",t.closeButtonAriaLabel),K(c)):F(c),e.className=_.popup,t.toast?(z([document.documentElement,document.body],_["toast-shown"]),z(e,_.toast)):z(e,_.modal),t.customClass&&z(e,t.customClass),t.customContainerClass&&z(s,t.customContainerClass),re(t),oe(t),ie(t),te(t),G(t.footer,u),!0===t.animation?W(e,_.noanimation):z(e,_.noanimation),t.showLoaderOnConfirm&&!t.preConfirm&&R("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request")}(M),Object.freeze(M),Pe.innerParams.set(this,M),le.timeout&&(le.timeout.stop(),delete le.t
79493imeout),clearTimeout(le.restoreFocusTimeout);var j={popup:k(),container:w(),content:B(),actions:Q(),confirmButton:L(),cancelButton:O(),closeButton:$(),validationMessage:E(),progressSteps:P()};Pe.domCache.set(this,j);var V=this.constructor;return new Promise(function(t,n){var o=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?t(e):t({value:e})},c=function(e){V.closePopup(M.onClose,M.onAfterClose),M.useRejections?n(e):t({dismiss:e})},u=function(e){V.closePopup(M.onClose,M.onAfterClose),n(e)};M.timer&&(le.timeout=new Te(function(){c("timer"),delete le.timeout},M.timer)),M.input&&setTimeout(function(){var e=T.getInput();e&&N(e)},0);for(var l=function(t){if(M.showLoaderOnConfirm&&V.showLoading(),M.preConfirm){T.resetValidationMessage();var e=Promise.resolve().then(function(){return M.preConfirm(t,M.extraParams)});M.expectRejections?e.then(function(e){return o(e||t)},function(e){T.hideLoading(),e&&T.showValidationMessage(e)}):e.then(function(e){Z(j.validationMessage)||!1===e?T.hideLoading():o(e||t)},function(e){return u(e)})}else o(t)},e=function(e){var t=e.target,n=j.confirmButton,o=j.cancelButton,i=n&&(n===t||n.contains(t)),r=o&&(o===t||o.contains(t));switch(e.type){case"click":if(i&&V.isVisible())if(T.disableButtons(),M.input){var a=function(){var e=T.getInput();if(!e)return null;switch(M.input){case"checkbox":return e.checked?1:0;case"radio":return e.checked?e.value:null;case"file":return e.files.length?e.files[0]:null;default:return M.inputAutoTrim?e.value.trim():e.value}}();if(M.inputValidator){T.disableInput();var s=Promise.resolve().then(function(){return M.inputValidator(a,M.extraParams)});M.expectRejections?s.then(function(){T.enableButtons(),T.enableInput(),l(a)},function(e){T.enableButtons(),T.enableInput(),e&&T.showValidationMessage(e)}):s.then(function(e){T.enableButtons(),T.enableInput(),e?T.showValidationMessage(e):l(a)},function(e){return u(e)})}else T.getInput().checkValidity()?l(a):(T.enableButtons(),T.showValidationMessage(M.validationMessage))}else l(!0);else r&&V.isVisible()&&(T.disableButtons(),c(V.DismissReason.cancel))}},i=j.popup.querySelectorAll("button"),r=0;r<i.length;r++)i[r].onclick=e,i[r].onmouseover=e,i[r].onmouseout=e,i[r].onmousedown=e;if(j.closeButton.onclick=function(){c(V.DismissReason.close)},M.toast)j.popup.onclick=function(){M.showConfirmButton||M.showCancelButton||M.showCloseButton||M.input||c(V.DismissReason.close)};else{var a=!1;j.popup.onmousedown=function(){j.container.onmouseup=function(e){j.container.onmouseup=void 0,e.target===j.container&&(a=!0)}},j.container.onmousedown=function(){j.popup.onmouseup=function(e){j.popup.onmouseup=void 0,(e.target===j.popup||j.popup.contains(e.target))&&(a=!0)}},j.container.onclick=function(e){a?a=!1:e.target===j.container&&H(M.allowOutsideClick)&&c(V.DismissReason.backdrop)}}M.reverseButtons?j.confirmButton.parentNode.insertBefore(j.cancelButton,j.confirmButton):j.confirmButton.parentNode.insertBefore(j.confirmButton,j.cancelButton);var s=function(e,t){for(var n=J(M.focusCancel),o=0;o<n.length;o++)return(e+=t)===n.length?e=0:-1===e&&(e=n.length-1),n[e].focus();j.popup.focus()};le.keydownHandlerAdded&&(le.keydownTarget.removeEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!1),M.toast||(le.keydownHandler=function(e){return function(e,t){if(t.stopKeydownPropagation&&e.stopPropagation(),"Enter"!==e.key||e.isComposing)if("Tab"===e.key){for(var n=e.target,o=J(t.focusCancel),i=-1,r=0;r<o.length;r++)if(n===o[r]){i=r;break}e.shiftKey?s(i,-1):s(i,1),e.stopPropagation(),e.preventDefault()}else-1!==["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Left","Right","Up","Down"].indexOf(e.key)?document.activeElement===j.confirmButton&&Z(j.cancelButton)?j.cancelButton.focus():document.activeElement===j.cancelButton&&Z(j.confirmButton)&&j.confirmButton.focus():"Escape"!==e.key&&"Esc"!==e.key||!0!==H(t.allowEscapeKey)||(e.preventDefault(),c(V.DismissReason.esc));else if(e.target&&T.getInput()&&e.target.outerHTML===T.getInput().outerHTML){if(-1!==["textarea","file"].indexOf(t.input))return;V.clickConfirm(),e.preventDefault()}}(e,M)},le.keydownTarget=M.keydownListenerCapture?window:j.popup,le.keydownListenerCapture=M.keydownListenerCapture,le.keydownTarget.addEventListener("keydown",le.keydownHandler,{capture:le.keydownListenerCapture}),le.keydownHandlerAdded=!0),T.enableButtons(),T.hideLoading(),T.resetValidationMessage(),M.toast&&(M.input||M.footer||M.showCloseButton)?z(document.body,_["toast-column"]):W(document.body,_["toast-column"]);for(var d,p,f=["input","file","range","select","radio","checkbox","textarea"],m=function(e){e.placeholder&&!M.inputPlaceholder||(e.placeholder=M.inputPlaceholder)},h=0;h<f.length;h++){var g=_[f[h]],b=U(j.content,g);if(d=T.getInput(f[h])){for(var v in d.attributes)if(d.attributes.hasOwnProperty(v)){var y=d.attributes[v].name;"type"!==y&&"value"!==y&&d.removeAttribute(y)}for(var w in M.inputAttributes)"range"===f[h]&&"placeholder"===w||d.setAttribute(w,M.inputAttributes[w])}b.className=g,M.inputClass&&z(b,M.inputClass),F(b)}switch(M.input){case"text":case"email":case"password":case"number":case"tel":case"url":d=U(j.content,_.input),"string"==typeof M.inputValue||"number"==typeof M.inputValue?d.value=M.inputValue:D(M.inputValue)||R('Unexpected type of inputValue! Expected "string", "number" or "Promise", got "'.concat(q(M.inputValue),'"')),m(d),d.type=M.input,
79493K(d);break;case"file":m(d=U(j.content,_.file)),d.type=M.input,K(d);break;case"range":var C=U(j.content,_.range),k=C.querySelector("input"),x=C.querySelector("output");k.value=M.inputValue,k.type=M.input,x.value=M.inputValue,K(C);break;case"select":var A=U(j.content,_.select);if(A.innerHTML="",M.inputPlaceholder){var B=document.createElement("option");B.innerHTML=M.inputPlaceholder,B.value="",B.disabled=!0,B.selected=!0,A.appendChild(B)}p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("option");o.value=t,o.innerHTML=n,M.inputValue.toString()===t.toString()&&(o.selected=!0),A.appendChild(o)}),K(A),A.focus()};break;case"radio":var S=U(j.content,_.radio);S.innerHTML="",p=function(e){e.forEach(function(e){var t=e[0],n=e[1],o=document.createElement("input"),i=document.createElement("label");o.type="radio",o.name=_.radio,o.value=t,M.inputValue.toString()===t.toString()&&(o.checked=!0);var r=document.createElement("span");r.innerHTML=n,r.className=_.label,i.appendChild(o),i.appendChild(r),S.appendChild(i)}),K(S);var t=S.querySelectorAll("input");t.length&&t[0].focus()};break;case"checkbox":var P=U(j.content,_.checkbox),E=T.getInput("checkbox");E.type="checkbox",E.value=1,E.id=_.checkbox,E.checked=Boolean(M.inputValue),P.querySelector("span").innerHTML=M.inputPlaceholder,K(P);break;case"textarea":var L=U(j.content,_.textarea);L.value=M.inputValue,m(L),K(L);break;case null:break;default:I('Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "'.concat(M.input,'"'))}if("select"===M.input||"radio"===M.input){var O=function(e){return p((t=e,n=[],"undefined"!=typeof Map&&t instanceof Map?t.forEach(function(e,t){n.push([t,e])}):Object.keys(t).forEach(function(e){n.push([e,t[e]])}),n));var t,n};D(M.inputOptions)?(V.showLoading(),M.inputOptions.then(function(e){T.hideLoading(),O(e)})):"object"===q(M.inputOptions)?O(M.inputOptions):I("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(q(M.inputOptions)))}else-1!==["text","email","number","tel","textarea"].indexOf(M.input)&&D(M.inputValue)&&(V.showLoading(),F(d),M.inputValue.then(function(e){d.value="number"===M.input?parseFloat(e)||0:e+"",K(d),d.focus(),T.hideLoading()}).catch(function(e){I("Error in inputValue promise: "+e),d.value="",K(d),d.focus(),T.hideLoading()}));je(M),M.toast||(H(M.allowEnterKey)?M.focusCancel&&Z(j.cancelButton)?j.cancelButton.focus():M.focusConfirm&&Z(j.confirmButton)?j.confirmButton.focus():s(-1,1):document.activeElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()),j.container.scrollTop=0})}});function Re(){if("undefined"!=typeof window){"undefined"==typeof Promise&&I("This package requires a Promise library, please include a shim to enable it in this browser (See: https://github.com/sweetalert2/sweetalert2/wiki/Migration-from-SweetAlert-to-SweetAlert2#1-ie-support)"),Ve=this;for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var o=Object.freeze(this.constructor.argsToParams(t));Object.defineProperties(this,{params:{value:o,writable:!1,enumerable:!0}});var i=this._main(this.params);Pe.promise.set(this,i)}}Re.prototype.then=function(e,t){return Pe.promise.get(this).then(e,t)},Re.prototype.catch=function(e){return Pe.promise.get(this).catch(e)},Re.prototype.finally=function(e){return Pe.promise.get(this).finally(e)},r(Re.prototype,qe),r(Re,Ae),Object.keys(qe).forEach(function(t){Re[t]=function(){var e;if(Ve)return(e=Ve)[t].apply(e,arguments)}}),Re.DismissReason=e,Re.noop=function(){};var Ie,He,De=fe((Ie=Re,He=function(e){function t(){return a(this,t),d(this,c(t).apply(this,arguments))}return s(t,Ie),i(t,[{key:"_main",value:function(e){return p(c(t.prototype),"_main",this).call(this,r({},Ce,e))}}],[{key:"setDefaults",value:function(t){if(m(we),!t||"object"!==q(t))throw new TypeError("SweetAlert2: The argument for setDefaults() is required and has to be a object");ye(t),Object.keys(t).forEach(function(e){Ie.isValidParameter(e)&&(Ce[e]=t[e])})}},{key:"resetDefaults",value:function(){m(we),Ce={}}}]),t}(),"undefined"!=typeof window&&"object"===q(window._swalDefaults)&&He.setDefaults(window._swalDefaults),He));return De.default=De}),"undefined"!=typeof window&&window.Sweetalert2&&(window.Sweetalert2.version="7.33.1",window.swal=window.sweetAlert=window.Swal=window.SweetAlert=window.Sweetalert2); 79494"use strict";
79495// Set defaults 79496swal.mixin({ 79497 width: 400, 79498 heightAuto: false, 79499 padding: '2.5rem', 79500 buttonsStyling: false, 79501 confirmButtonClass: 'btn btn-success', 79502 confirmButtonColor: null, 79503 cancelButtonClass: 'btn btn-secondary', 79504 cancelButtonColor: null 79505}); 79506var identity = function (x) { 79507 return x; 79508}; 79509 79510var isArray = function (value) { 79511 return $.isArray(value); 79512}; 79513 79514var isObject = function (value) { 79515 return !isArray(value) && (value instanceof Object); 79516}; 79517 79518var isNumber = function (value) { 79519 return value instanceof Number; 79520}; 79521 79522var isFunction = function (value) { 79523 return value instanceof Function; 79524}; 79525 79526var indexOf = function (object, value) { 79527 return $.inArray(value, object); 79528}; 79529 79530var inArray = function (array, value) { 79531 return indexOf(array, value) !== -1; 79532}; 79533 79534var foreach = function (collection, callback) { 79535 for(var i in collection) { 79536 if(collection.hasOwnProperty(i)) { 79537 callback(collection[i], i, collection); 79538 } 79539 } 79540}; 79541 79542 79543var last = function (array) { 79544 return array[array.length - 1]; 79545}; 79546 79547var argumentsToArray = function (args) { 79548 return Array.prototype.slice.call(args); 79549}; 79550 79551var extend = function () { 79552 var extended = {}; 79553 foreach(argumentsToArray(arguments), function (o) { 79554 foreach(o, function (val, key) { 79555 extended[key] = val; 79556 }); 79557 }); 79558 return extended; 79559}; 79560 79561var mapToArray = function (collection, callback) { 79562 var mapped = []; 79563 foreach(collection, function (value, key, coll) { 79564 mapped.push(callback(value, key, coll)); 79565 }); 79566 return mapped; 79567}; 79568 79569var mapToObject = function (collection, callback, keyCallback) { 79570 var mapped = {}; 79571 foreach(collection, function (value, key, coll) { 79572 key = keyCallback ? keyCallback(key, value) : key; 79573 mapped[key] = callback(value, key, coll); 79574 }); 79575 return mapped; 79576}; 79577 79578var map = function (collection, callback, keyCallback) { 79579 return isArray(collection) ? 79580 mapToArray(collection, callback) : 79581 mapToObject(collection, callback, keyCallback); 79582}; 79583 79584var pluck = function (arrayOfObjects, key) { 79585 return map(arrayOfObjects, function (val) { 79586 return val[key]; 79587 }); 79588}; 79589 79590var filter = function (collection, callback) { 79591 var filtered; 79592 79593 if(isArray(collection)) { 79594 filtered = []; 79595 foreach(collection, function (val, key, coll) { 79596 if(callback(val, key, coll)) { 79597 filtered.push(val); 79598 } 79599 }); 79600 } 79601 else { 79602 filtered = {}; 79603 foreach(collection, function (val, key, coll) { 79604 if(callback(val, key, coll)) { 79605 filtered[key] = val; 79606 } 79607 }); 79608 } 79609 79610 return filtered; 79611}; 79612 79613var call = function (collection, functionName, args) { 79614 return map(collection, function (object, name) { 79615 return object[functionName].apply(object, args || []); 79616 }); 79617}; 79618 79619//execute callback immediately and at most one time on the minimumInterval, 79620//ignore block attempts 79621var throttle = function (minimumInterval, callback) { 79622 var timeout = null; 79623 return function () { 79624 var that = this, args = arguments; 79625 if(timeout === null) { 79626 timeout = setTimeout(function () { 79627 timeout = null; 79628 }, minimumInterval); 79629 callback.apply(that, args); 79630 } 79631 }; 79632}; 79633 79634 79635var mixinPubSub = function (object) { 79636 object = object || {}; 79637 var topics = {}; 79638 79639 object.publish = function (topic, data) { 79640 foreach(topics[topic], function (callback) { 79641 callback(data); 79642 }); 79643 }; 79644 79645 object.subscribe = function (topic, callback) { 79646 topics[topic] = topics[topic] || []; 79647 topics[topic].push(callback); 79648 }; 79649 79650 object.unsubscribe = function (callback) { 79651 foreach(topics, function (subscribers) { 79652 var index = indexOf(subscribers, callback); 79653 if(index !== -1) { 79654 subscribers.splice(index, 1); 79655 } 79656 }); 79657 }; 79658 79659 return object; 79660}; 79661 79662// jquery.input version 0.0.0 79663// https://github.com/DubFriend/jquery.input 79664// (MIT) 09-04-2014 79665// Brian Detering <[email protected]> (http://www.briandetering.net/) 79666(function ($) { 79667'use strict'; 79668 79669var createBaseInput = function (fig, my) { 79670 var self = mixinPubSub(), 79671 $self = fig.$; 79672 79673 self.getType = function () { 79674 throw 'implement me (return type. "text", "radio", etc.)'; 79675 }; 79676 79677 self.$ = function (selector) { 79678 return selector ? $self.find(selector) : $self; 79679 }; 79680 79681 self.disable = function () { 79682 self.$().prop('disabled', true); 79683 self.publish('isEnabled', false); 79684 }; 79685 79686 self.enable = function () { 79687 self.$().prop('disabled', false); 79688 self.publish('isEnabled', true); 79689 }; 79690 79691 my.equalTo = function (a, b) { 79692 return a === b; 79693 }; 79694 79695 my.publishChange = (function () { 79696 var oldValue; 79697 return function (e, domElement) { 79698 var newValue = self.get(); 79699 if(!my.equalTo(newValue, oldValue)) { 79700 self.publish('change', { e: e, domElement: domElement }); 79701 } 79702 oldValue = newValue; 79703 }; 79704 }()); 79705 79706 return self; 79707}; 79708 79709 79710var createInput = function (fig, my) { 79711 var self = createBaseInput(fig, my); 79712 79713 self.get = function () { 79714 return self.$().val(); 79715 }; 79716 79717 self.set = function (newValue) { 79718 self.$().val(newValue); 79719 }; 79720 79721 self.clear = function () { 79722 self.set(''); 79723 }; 79724 79725 my.buildSetter = function (callback) { 79726 return function (newValue) { 79727 callback.call(self, newValue); 79728 }; 79729 }; 79730 79731 return self; 79732}; 79733 79734var inputEqualToArray = function (a, b) { 79735 a = isArray(a) ? a : [a]; 79736 b = isArray(b) ? b : [b]; 79737 79738 var isEqual = true; 79739 if(a.length !== b.length) { 79740 isEqual = false;
79741 } 79742 else { 79743 foreach(a, function (value) { 79744 if(!inArray(b, value)) { 79745 isEqual = false; 79746 } 79747 }); 79748 } 79749 79750 return isEqual; 79751}; 79752 79753var createInputButton = function (fig) { 79754 var my = {}, 79755 self = createInput(fig, my); 79756 79757 self.getType = function () { 79758 return 'button'; 79759 }; 79760 79761 self.$().on('change', function (e) { 79762 my.publishChange(e, this); 79763 }); 79764 79765 return self; 79766}; 79767 79768var createInputCheckbox = function (fig) { 79769 var my = {}, 79770 self = createInput(fig, my); 79771 79772 self.getType = function () { 79773 return 'checkbox'; 79774 }; 79775 79776 self.get = function () { 79777 var values = []; 79778 self.$().filter(':checked').each(function () { 79779 values.push($(this).val()); 79780 }); 79781 return values; 79782 }; 79783 79784 self.set = function (newValues) { 79785 newValues = isArray(newValues) ? newValues : [newValues]; 79786 79787 self.$().each(function () { 79788 $(this).prop('checked', false); 79789 }); 79790 79791 foreach(newValues, function (value) { 79792 self.$().filter('[value="' + value + '"]') 79793 .prop('checked', true); 79794 }); 79795 }; 79796 79797 my.equalTo = inputEqualToArray; 79798 79799 self.$().change(function (e) { 79800 my.publishChange(e, this); 79801 }); 79802 79803 return self; 79804}; 79805 79806var createInputEmail = function (fig) { 79807 var my = {}, 79808 self = createInputText(fig, my); 79809 79810 self.getType = function () { 79811 return 'email'; 79812 }; 79813 79814 return self; 79815}; 79816 79817var createInputFile = function (fig) { 79818 var my = {}, 79819 self = createBaseInput(fig, my); 79820 79821 self.getType = function () { 79822 return 'file'; 79823 }; 79824 79825 self.get = function () { 79826 return last(self.$().val().split('\\')); 79827 }; 79828 79829 self.clear = function () { 79830 // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery 79831 this.$().each(function () { 79832 $(this).wrap('<form>').closest('form').get(0).reset(); 79833 $(this).unwrap(); 79834 }); 79835 }; 79836 79837 self.$().change(function (e) { 79838 my.publishChange(e, this); 79839 // self.publish('change', self); 79840 }); 79841 79842 return self; 79843}; 79844 79845var createInputHidden = function (fig) { 79846 var my = {}, 79847 self = createInput(fig, my); 79848 79849 self.getType = function () { 79850 return 'hidden'; 79851 }; 79852 79853 self.$().change(function (e) { 79854 my.publishChange(e, this); 79855 }); 79856 79857 return self; 79858}; 79859var createInputMultipleFile = function (fig) { 79860 var my = {}, 79861 self = createBaseInput(fig, my); 79862 79863 self.getType = function () { 79864 return 'file[multiple]'; 79865 }; 79866 79867 self.get = function () { 79868 // http://stackoverflow.com/questions/14035530/how-to-get-value-of-html-5-multiple-file-upload-variable-using-jquery 79869 var fileListObject = self.$().get(0).files || [], 79870 names = [], i; 79871 79872 for(i = 0; i < (fileListObject.length || 0); i += 1) { 79873 names.push(fileListObject[i].name); 79874 } 79875 79876 return names; 79877 }; 79878 79879 self.clear = function () { 79880 // http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery 79881 this.$().each(function () { 79882 $(this).wrap('<form>').closest('form').get(0).reset(); 79883 $(this).unwrap(); 79884 }); 79885 }; 79886 79887 self.$().change(function (e) { 79888 my.publishChange(e, this); 79889 }); 79890 79891 return self; 79892}; 79893 79894var createInputMultipleSelect = function (fig) { 79895 var my = {}, 79896 self = createInput(fig, my); 79897 79898 self.getType = function () { 79899 return 'select[multiple]'; 79900 }; 79901 79902 self.get = function () { 79903 return self.$().val() || []; 79904 }; 79905 79906 self.set = function (newValues) { 79907 self.$().val( 79908 newValues === '' ? [] : isArray(newValues) ? newValues : [newValues] 79909 ); 79910 }; 79911 79912 my.equalTo = inputEqualToArray; 79913 79914 self.$().change(function (e) { 79915 my.publishChange(e, this); 79916 }); 79917 79918 return self; 79919}; 79920 79921var createInputPassword = function (fig) { 79922 var my = {}, 79923 self = createInputText(fig, my); 79924 79925 self.getType = function () { 79926 return 'password'; 79927 }; 79928 79929 return self; 79930}; 79931 79932var createInputRadio = function (fig) { 79933 var my = {}, 79934 self = createInput(fig, my); 79935 79936 self.getType = function () { 79937 return 'radio'; 79938 }; 79939 79940 self.get = function () { 79941 return self.$().filter(':checked').val() || null; 79942 }; 79943 79944 self.set = function (newValue) { 79945 if(!newValue) { 79946 self.$().each(function () { 79947 $(this).prop('checked', false); 79948 }); 79949 } 79950 else { 79951 self.$().filter('[value="' + newValue + '"]').prop('checked', true); 79952 } 79953 }; 79954 79955 self.$().change(function (e) { 79956 my.publishChange(e, this); 79957 }); 79958 79959 return self; 79960}; 79961 79962var createInputRange = function (fig) { 79963 var my = {}, 79964 self = createInput(fig, my); 79965 79966 self.getType = function () { 79967 return 'range'; 79968 }; 79969 79970 self.$().change(function (e) { 79971 my.publishChange(e, this); 79972 }); 79973 79974 return self; 79975}; 79976 79977var createInputSelect = function (fig) { 79978 var my = {}, 79979 self = createInput(fig, my); 79980 79981 self.getType = function () { 79982 return 'select'; 79983 }; 79984 79985 self.$().change(function (e) { 79986 my.publishChange(e, this); 79987 }); 79988 79989 return self; 79990}; 79991 79992var createInputText = function (fig) { 79993 var my = {}, 79994 self = createInput(fig, my); 79995 79996 self.getType = function () { 79997 return 'text'; 79998 }; 79999 80000 self.$().on('change keyup keydown', function (e) { 80001 my.publishChange(e, this); 80002 }); 80003 80004 return self; 80005}; 80006 80007var createInputTextarea = function (fig) { 80008 var my = {}, 80009 self = createInput(fig, my); 80010 80011 self.getType = function () { 80012 return 'textarea'; 80013 }; 80014 80015 self.$().on('change keyup keydown', function (e) { 80016 my.publishChange(e, this); 80017 }); 80018 80019 return self; 80020}; 80021 80022var createInputURL = function (fig) { 80023 var my = {}, 80024 self = createInputText(fig, my); 80025 80026 self.getType = function () { 80027 return 'url'; 80028 }; 80029 80030 return self; 80031}; 80032 80033var buildFormInputs = function (fig) { 80034 var inputs = {}, 80035 $self = fig.$; 80036 80037 var constructor = fig.constructorOverride || { 80038 button: createInputButton, 80039 text: createInputText, 80040 url: createInputURL, 80041 email: createInputEmail, 80042 password: createInputPassword, 80043 range: createInputRange, 80044 textarea: createInputTextarea,
80045 select: createInputSelect, 80046 'select[multiple]': createInputMultipleSelect, 80047 radio: createInputRadio, 80048 checkbox: createInputCheckbox, 80049 file: createInputFile, 80050 'file[multiple]': createInputMultipleFile, 80051 hidden: createInputHidden 80052 }; 80053 80054 var addInputsBasic = function (type, selector) { 80055 var $input = isObject(selector) ? selector : $self.find(selector); 80056 80057 $input.each(function () { 80058 var name = $(this).attr('name'); 80059 inputs[name] = constructor[type]({ 80060 $: $(this) 80061 }); 80062 }); 80063 }; 80064 80065 var addInputsGroup = function (type, selector) { 80066 var names = [], 80067 $input = isObject(selector) ? selector : $self.find(selector); 80068 80069 if(isObject(selector)) { 80070 inputs[$input.attr('name')] = constructor[type]({ 80071 $: $input 80072 }); 80073 } 80074 else { 80075 // group by name attribute 80076 $input.each(function () { 80077 if(indexOf(names, $(this).attr('name')) === -1) { 80078 names.push($(this).attr('name')); 80079 } 80080 }); 80081 80082 foreach(names, function (name) { 80083 inputs[name] = constructor[type]({ 80084 $: $self.find('input[name="' + name + '"]') 80085 }); 80086 }); 80087 } 80088 }; 80089 80090 80091 if($self.is('input, select, textarea')) { 80092 if($self.is('input[type="button"], button, input[type="submit"]')) { 80093 addInputsBasic('button', $self); 80094 } 80095 else if($self.is('textarea')) { 80096 addInputsBasic('textarea', $self); 80097 } 80098 else if( 80099 $self.is('input[type="text"]') || 80100 $self.is('input') && !$self.attr('type') 80101 ) { 80102 addInputsBasic('text', $self); 80103 } 80104 else if($self.is('input[type="password"]')) { 80105 addInputsBasic('password', $self); 80106 } 80107 else if($self.is('input[type="email"]')) { 80108 addInputsBasic('email', $self); 80109 } 80110 else if($self.is('input[type="url"]')) { 80111 addInputsBasic('url', $self); 80112 } 80113 else if($self.is('input[type="range"]')) { 80114 addInputsBasic('range', $self); 80115 } 80116 else if($self.is('select')) { 80117 if($self.is('[multiple]')) { 80118 addInputsBasic('select[multiple]', $self); 80119 } 80120 else { 80121 addInputsBasic('select', $self); 80122 } 80123 } 80124 else if($self.is('input[type="file"]')) { 80125 if($self.is('[multiple]')) { 80126 addInputsBasic('file[multiple]', $self); 80127 } 80128 else { 80129 addInputsBasic('file', $self); 80130 } 80131 } 80132 else if($self.is('input[type="hidden"]')) { 80133 addInputsBasic('hidden', $self); 80134 } 80135 else if($self.is('input[type="radio"]')) { 80136 addInputsGroup('radio', $self); 80137 } 80138 else if($self.is('input[type="checkbox"]')) { 80139 addInputsGroup('checkbox', $self); 80140 } 80141 else { 80142 //in all other cases default to a "text" input interface. 80143 addInputsBasic('text', $self); 80144 } 80145 } 80146 else { 80147 addInputsBasic('button', 'input[type="button"], button, input[type="submit"]'); 80148 addInputsBasic('text', 'input[type="text"]'); 80149 addInputsBasic('password', 'input[type="password"]'); 80150 addInputsBasic('email', 'input[type="email"]'); 80151 addInputsBasic('url', 'input[type="url"]'); 80152 addInputsBasic('range', 'input[type="range"]'); 80153 addInputsBasic('textarea', 'textarea'); 80154 addInputsBasic('select', 'select:not([multiple])'); 80155 addInputsBasic('select[multiple]', 'select[multiple]'); 80156 addInputsBasic('file', 'input[type="file"]:not([multiple])'); 80157 addInputsBasic('file[multiple]', 'input[type="file"][multiple]'); 80158 addInputsBasic('hidden', 'input[type="hidden"]'); 80159 addInputsGroup('radio', 'input[type="radio"]'); 80160 addInputsGroup('checkbox', 'input[type="checkbox"]'); 80161 } 80162
80163 return inputs; 80164}; 80165 80166$.fn.inputVal = function (newValue) { 80167 var $self = $(this); 80168 80169 var inputs = buildFormInputs({ $: $self }); 80170 80171 if($self.is('input, textarea, select')) { 80172 if(typeof newValue === 'undefined') { 80173 return inputs[$self.attr('name')].get(); 80174 } 80175 else { 80176 inputs[$self.attr('name')].set(newValue); 80177 return $self; 80178 } 80179 } 80180 else { 80181 if(typeof newValue === 'undefined') { 80182 return call(inputs, 'get'); 80183 } 80184 else { 80185 foreach(newValue, function (value, inputName) { 80186 inputs[inputName].set(value); 80187 }); 80188 return $self; 80189 } 80190 } 80191}; 80192 80193$.fn.inputOnChange = function (callback) { 80194 var $self = $(this); 80195 var inputs = buildFormInputs({ $: $self }); 80196 foreach(inputs, function (input) { 80197 input.subscribe('change', function (data) { 80198 callback.call(data.domElement, data.e); 80199 }); 80200 }); 80201 return $self; 80202}; 80203 80204$.fn.inputDisable = function () { 80205 var $self = $(this); 80206 call(buildFormInputs({ $: $self }), 'disable'); 80207 return $self; 80208}; 80209 80210$.fn.inputEnable = function () { 80211 var $self = $(this); 80212 call(buildFormInputs({ $: $self }), 'enable'); 80213 return $self; 80214}; 80215 80216$.fn.inputClear = function () { 80217 var $self = $(this); 80218 call(buildFormInputs({ $: $self }), 'clear'); 80219 return $self; 80220}; 80221 80222}(jQuery)); 80223 80224$.fn.repeaterVal = function () { 80225 var parse = function (raw) { 80226 var parsed = []; 80227 80228 foreach(raw, function (val, key) { 80229 var parsedKey = []; 80230 if(key !== "undefined") { 80231 parsedKey.push(key.match(/^[^\[]*/)[0]); 80232 parsedKey = parsedKey.concat(map( 80233 key.match(/\[[^\]]*\]/g), 80234 function (bracketed) { 80235 return bracketed.replace(/[\[\]]/g, ''); 80236 } 80237 )); 80238 80239 parsed.push({ 80240 val: val, 80241 key: parsedKey 80242 }); 80243 } 80244 }); 80245 80246 return parsed; 80247 }; 80248 80249 var build = function (parsed) { 80250 if( 80251 parsed.length === 1 && 80252 (parsed[0].key.length === 0 || parsed[0].key.length === 1 && !parsed[0].key[0]) 80253 ) { 80254 return parsed[0].val; 80255 } 80256 80257 foreach(parsed, function (p) { 80258 p.head = p.key.shift(); 80259 }); 80260 80261 var grouped = (function () { 80262 var grouped = {}; 80263 80264 foreach(parsed, function (p) { 80265 if(!grouped[p.head]) { 80266 grouped[p.head] = []; 80267 } 80268 grouped[p.head].push(p); 80269 }); 80270 80271 return grouped; 80272 }()); 80273 80274 var built; 80275 80276 if(/^[0-9]+$/.test(parsed[0].head)) { 80277 built = []; 80278 foreach(grouped, function (group) { 80279 built.push(build(group)); 80280 }); 80281 } 80282 else { 80283 built = {}; 80284 foreach(grouped, function (group, key) { 80285 built[key] = build(group); 80286 }); 80287 } 80288 80289 return built; 80290 }; 80291 80292 return build(parse($(this).inputVal())); 80293}; 80294 80295$.fn.repeater = function (fig) { 80296 fig = fig || {}; 80297 80298 var setList; 80299 80300 $(this).each(function () { 80301 80302 var $self = $(this); 80303 80304 var show = fig.show || function () { 80305 $(this).show(); 80306 }; 80307 80308 var hide = fig.hide || function (removeElement) { 80309 removeElement(); 80310 }; 80311 80312 var $list = $self.find('[data-repeater-list]').first(); 80313 80314 var $filterNested = function ($items, repeaters) { 80315 return $items.filter(function () { 80316 return repeaters ? 80317 $(this).closest( 80318 pluck(repeaters, 'selector').join(',') 80319 ).length === 0 : true; 80320 }); 80321 }; 80322 80323 var $items = function () { 80324 return $filterNested($list.find('[data-repeater-item]'), fig.repeaters); 80325 }; 80326 80327 var $itemTemplate = $list.find('[data-repeater-item]') 80328 .first().clone().hide(); 80329 80330 var $firstDeleteButton = $filterNested( 80331 $filterNested($(this).find('[data-repeater-item]'), fig.repeaters) 80332 .first().find('[data-repeater-delete]'), 80333 fig.repeaters 80334 ); 80335 80336 if(fig.isFirstItemUndeletable && $firstDeleteButton) { 80337 $firstDeleteButton.remove(); 80338 } 80339 80340 var getGroupName = function () { 80341 var groupName = $list.data('repeater-list'); 80342 return fig.$parent ? 80343 fig.$parent.data('item-name') + '[' + groupName + ']' : 80344 groupName; 80345 }; 80346 80347 var initNested = function ($listItems) { 80348 if(fig.repeaters) { 80349 $listItems.each(function () { 80350 var $item = $(this); 80351 foreach(fig.repeaters, function (nestedFig) { 80352 $item.find(nestedFig.selector).repeater(extend( 80353 nestedFig, { $parent: $item } 80354 )); 80355 }); 80356 }); 80357 } 80358 }; 80359 80360 var $foreachRepeaterInItem = function (repeaters, $item, cb) { 80361 if(repeaters) { 80362 foreach(repeaters, function (nestedFig) { 80363 cb.call($item.find(nestedFig.selector)[0], nestedFig); 80364 }); 80365 } 80366 }; 80367
80368 var setIndexes = function ($items, groupName, repeaters) { 80369 $items.each(function (index) { 80370 var $item = $(this); 80371 $item.data('item-name', groupName + '[' + index + ']'); 80372 $filterNested($item.find('[name]'), repeaters) 80373 .each(function () { 80374 var $input = $(this); 80375 // match non empty brackets (ex: "[foo]") 80376 var matches = $input.attr('name').match(/\[[^\]]+\]/g); 80377 80378 var name = matches ? 80379 // strip "[" and "]" characters 80380 last(matches).replace(/\[|\]/g, '') : 80381 $input.attr('name'); 80382 80383 80384 var newName = groupName + '[' + index + '][' + name + ']' + 80385 ($input.is(':checkbox') || $input.attr('multiple') ? '[]' : ''); 80386 80387 $input.attr('name', newName); 80388 80389 $foreachRepeaterInItem(repeaters, $item, function (nestedFig) { 80390 var $repeater = $(this); 80391 setIndexes( 80392 $filterNested($repeater.find('[data-repeater-item]'), nestedFig.repeaters || []), 80393 groupName + '[' + index + ']' + 80394 '[' + $repeater.find('[data-repeater-list]').first().data('repeater-list') + ']', 80395 nestedFig.repeaters 80396 ); 80397 }); 80398 }); 80399 }); 80400 80401 $list.find('input[name][checked]') 80402 .removeAttr('checked') 80403 .prop('checked', true); 80404 }; 80405 80406 setIndexes($items(), getGroupName(), fig.repeaters); 80407 initNested($items()); 80408 if(fig.initEmpty) { 80409 $items().remove(); 80410 } 80411 80412 if(fig.ready) { 80413 fig.ready(function () { 80414 setIndexes($items(), getGroupName(), fig.repeaters); 80415 }); 80416 } 80417 80418 var appendItem = (function () { 80419 var setItemsValues = function ($item, data, repeaters) { 80420 if(data || fig.defaultValues) { 80421 var inputNames = {}; 80422 $filterNested($item.find('[name]'), repeaters).each(function () { 80423 var key = $(this).attr('name').match(/\[([^\]]*)(\]|\]\[\])$/)[1]; 80424 inputNames[key] = $(this).attr('name'); 80425 }); 80426 80427 $item.inputVal(map( 80428 filter(data || fig.defaultValues, function (val, name) { 80429 return inputNames[name]; 80430 }), 80431 identity, 80432 function (name) { 80433 return inputNames[name]; 80434 } 80435 )); 80436 } 80437 80438 80439 $foreachRepeaterInItem(repeaters, $item, function (nestedFig) { 80440 var $repeater = $(this); 80441 $filterNested( 80442 $repeater.find('[data-repeater-item]'), 80443 nestedFig.repeaters 80444 ) 80445 .each(function () { 80446 var fieldName = $repeater.find('[data-repeater-list]').data('repeater-list'); 80447 if(data && data[fieldName]) { 80448 var $template = $(this).clone(); 80449 $repeater.find('[data-repeater-item]').remove(); 80450 foreach(data[fieldName], function (data) { 80451 var $item = $template.clone(); 80452 setItemsValues( 80453 $item, 80454 data, 80455 nestedFig.repeaters || [] 80456 ); 80457 $repeater.find('[data-repeater-list]').append($item); 80458 }); 80459 } 80460 else { 80461 setItemsValues( 80462 $(this), 80463 nestedFig.defaultValues, 80464 nestedFig.repeaters || [] 80465 ); 80466 } 80467 }); 80468 }); 80469 80470 }; 80471 80472 return function ($item, data) { 80473 $list.append($item);
80474 setIndexes($items(), getGroupName(), fig.repeaters); 80475 $item.find('[name]').each(function () { 80476 $(this).inputClear(); 80477 }); 80478 setItemsValues($item, data || fig.defaultValues, fig.repeaters); 80479 }; 80480 }()); 80481 80482 var addItem = function (data) { 80483 var $item = $itemTemplate.clone(); 80484 appendItem($item, data); 80485 if(fig.repeaters) { 80486 initNested($item); 80487 } 80488 show.call($item.get(0)); 80489 }; 80490 80491 setList = function (rows) { 80492 $items().remove(); 80493 foreach(rows, addItem); 80494 }; 80495 80496 $filterNested($self.find('[data-repeater-create]'), fig.repeaters).click(function () { 80497 addItem(); 80498 }); 80499 80500 $list.on('click', '[data-repeater-delete]', function () { 80501 var self = $(this).closest('[data-repeater-item]').get(0); 80502 hide.call(self, function () { 80503 $(self).remove(); 80504 setIndexes($items(), getGroupName(), fig.repeaters); 80505 }); 80506 }); 80507 }); 80508 80509 this.setList = setList; 80510 80511 return this; 80512}; 80513 80514(function (global, factory) { 80515 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 80516 typeof define === 'function' && define.amd ? define(factory) : 80517 (global.DOMPurify = factory()); 80518}(this, (function () { 'use strict'; 80519 80520var freeze$1 = Object.freeze || function (x) { 80521 return x; 80522}; 80523 80524var html = freeze$1(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']); 80525 80526// SVG 80527var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']); 80528 80529var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']); 80530 80531var mathMl = freeze$1(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']); 80532 80533var text = freeze$1(['#text']); 80534 80535var freeze$2 = Object.freeze || function (x) { 80536 return x; 80537}; 80538 80539var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']); 80540 80541var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', '
80541y1', 'y2', 'z', 'zoomandpan']); 80542 80543var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']); 80544 80545var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']); 80546 80547var hasOwnProperty = Object.hasOwnProperty; 80548var setPrototypeOf = Object.setPrototypeOf; 80549 80550var _ref$1 = typeof Reflect !== 'undefined' && Reflect; 80551var apply$1 = _ref$1.apply; 80552 80553if (!apply$1) { 80554 apply$1 = function apply(fun, thisValue, args) { 80555 return fun.apply(thisValue, args); 80556 }; 80557} 80558 80559/* Add properties to a lookup table */ 80560function addToSet(set, array) { 80561 if (setPrototypeOf) { 80562 // Make 'in' and truthy checks like Boolean(set.constructor) 80563 // independent of any properties defined on Object.prototype. 80564 // Prevent prototype setters from intercepting set as a this value. 80565 setPrototypeOf(set, null); 80566 } 80567 80568 var l = array.length; 80569 while (l--) { 80570 var element = array[l]; 80571 if (typeof element === 'string') { 80572 var lcElement = element.toLowerCase(); 80573 if (lcElement !== element) { 80574 // Config presets (e.g. tags.js, attrs.js) are immutable. 80575 if (!Object.isFrozen(array)) { 80576 array[l] = lcElement; 80577 } 80578 80579 element = lcElement; 80580 } 80581 } 80582 80583 set[element] = true; 80584 } 80585 80586 return set; 80587} 80588 80589/* Shallow clone an object */ 80590function clone(object) { 80591 var newObject = {}; 80592 80593 var property = void 0; 80594 for (property in object) { 80595 if (apply$1(hasOwnProperty, object, [property])) { 80596 newObject[property] = object[property]; 80597 } 80598 } 80599 80600 return newObject; 80601} 80602 80603var seal = Object.seal || function (x) { 80604 return x; 80605}; 80606 80607var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode 80608var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm); 80609var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape 80610var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape 80611var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape 80612); 80613var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i); 80614var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex 80615); 80616 80617var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 80618 80619function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 80620 80621var _ref = typeof Reflect !== 'undefined' && Reflect; 80622var apply = _ref.apply; 80623 80624var arraySlice = Array.prototype.slice; 80625var freeze = Object.freeze; 80626 80627var getGlobal = function getGlobal() { 80628 return typeof window === 'undefined' ? null : window; 80629}; 80630 80631if (!apply) { 80632 apply = function apply(fun, thisValue, args) { 80633 return fun.apply(thisValue, args); 80634 }; 80635} 80636 80637/** 80638 * Creates a no-op policy for internal use only. 80639 * Don't export this function outside this module! 80640 * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory. 80641 * @param {Document} document The document object (to determine policy name suffix) 80642 * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types 80643 * are not supported). 80644 */ 80645var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) { 80646 if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') { 80647 return null; 80648 } 80649 80650 // Allow the callers to control the unique policy name 80651 // by adding a data-tt-policy-suffix to the script element with the DOMPurify. 80652 // Policy creation with duplicate names throws in Trusted Types. 80653 var suffix = null; 80654 var ATTR_NAME = 'data-tt-policy-suffix'; 80655 if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) { 80656 suffix = document.currentScript.getAttribute(ATTR_NAME); 80657 } 80658 80659 var policyName = 'dompurify' + (suffix ? '#' + suffix : ''); 80660 80661 try { 80662 return trustedTypes.createPolicy(policyName, { 80663 createHTML: function createHTML(html$$1) { 80664 return html$$1; 80665 } 80666 }); 80667 } catch (error) { 80668 // Policy creation failed (most likely another DOMPurify script has 80669 // already run). Skip creating the policy, as this will only cause errors 80670 // if TT are enforced. 80671 console.warn('TrustedTypes policy ' + policyName + ' could not be created.'); 80672 return null; 80673 } 80674}; 80675 80676function createDOMPurify() { 80677 var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); 80678 80679 var DOMPurify = function DOMPurify(root) { 80680 return createDOMPurify(root); 80681 }; 80682 80683 /** 80684 * Version label, exposed for easier checks 80685 * if DOMPurify is up to date or not 80686 */ 80687 DOMPurify.version = '1.0.10'; 80688 80689 /** 80690 * Array of elements that DOMPurify removed during sanitation. 80691 * Empty if nothing was removed. 80692 */ 80693 DOMPurify.removed = []; 80694 80695 if (!window || !window.document || window.document.nodeType !== 9) { 80696 // Not running in a browser, provide a factory function 80697 // so that you can pass your own Window 80698 DOMPurify.isSupported = false;
80699 80700 return DOMPurify; 80701 } 80702 80703 var originalDocument = window.document; 80704 var useDOMParser = false; 80705 var removeTitle = false; 80706 80707 var document = window.document; 80708 var DocumentFragment = window.DocumentFragment, 80709 HTMLTemplateElement = window.HTMLTemplateElement, 80710 Node = window.Node, 80711 NodeFilter = window.NodeFilter, 80712 _window$NamedNodeMap = window.NamedNodeMap, 80713 NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, 80714 Text = window.Text, 80715 Comment = window.Comment, 80716 DOMParser = window.DOMParser, 80717 TrustedTypes = window.TrustedTypes; 80718 80719 // As per issue #47, the web-components registry is inherited by a 80720 // new document created via createHTMLDocument. As per the spec 80721 // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) 80722 // a new empty registry is used when creating a template contents owner 80723 // document, so we use that as our parent document to ensure nothing 80724 // is inherited. 80725 80726 if (typeof HTMLTemplateElement === 'function') { 80727 var template = document.createElement('template'); 80728 if (template.content && template.content.ownerDocument) { 80729 document = template.content.ownerDocument; 80730 } 80731 } 80732 80733 var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument); 80734 var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : ''; 80735 80736 var _document = document, 80737 implementation = _document.implementation, 80738 createNodeIterator = _document.createNodeIterator, 80739 getElementsByTagName = _document.getElementsByTagName, 80740 createDocumentFragment = _document.createDocumentFragment; 80741 var importNode = originalDocument.importNode; 80742 80743 80744 var hooks = {}; 80745 80746 /** 80747 * Expose whether this browser supports running the full DOMPurify. 80748 */ 80749 DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9; 80750 80751 var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR, 80752 ERB_EXPR$$1 = ERB_EXPR, 80753 DATA_ATTR$$1 = DATA_ATTR, 80754 ARIA_ATTR$$1 = ARIA_ATTR, 80755 IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA, 80756 ATTR_WHITESPACE$$1 = ATTR_WHITESPACE; 80757 var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI; 80758 /** 80759 * We consider the elements and attributes below to be safe. Ideally 80760 * don't add any new ones but feel free to remove unwanted ones. 80761 */ 80762 80763 /* allowed element names */ 80764 80765 var ALLOWED_TAGS = null; 80766 var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text))); 80767 80768 /* Allowed attribute names */ 80769 var ALLOWED_ATTR = null; 80770 var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml))); 80771 80772 /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */ 80773 var FORBID_TAGS = null; 80774 80775 /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */ 80776 var FORBID_ATTR = null; 80777 80778 /* Decide if ARIA attributes are okay */ 80779 var ALLOW_ARIA_ATTR = true; 80780 80781 /* Decide if custom data attributes are okay */ 80782 var ALLOW_DATA_ATTR = true; 80783 80784 /* Decide if unknown protocols are okay */ 80785 var ALLOW_UNKNOWN_PROTOCOLS = false; 80786 80787 /* Output should be safe for jQuery's $() factory? */ 80788 var SAFE_FOR_JQUERY = false; 80789 80790 /* Output should be safe for common template engines. 80791 * This means, DOMPurify removes data attributes, mustaches and ERB 80792 */ 80793 var SAFE_FOR_TEMPLATES = false; 80794 80795 /* Decide if document with <html>... should be returned */ 80796 var WHOLE_DOCUMENT = false; 80797 80798 /* Track whether config is already set on this instance of DOMPurify. */ 80799 var SET_CONFIG = false; 80800 80801 /* Decide if all elements (e.g. style, script) must be children of 80802 * document.body. By default, browsers might move them to document.head */ 80803 var FORCE_BODY = false;
80804 80805 /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html 80806 * string (or a TrustedHTML object if Trusted Types are supported). 80807 * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead 80808 */ 80809 var RETURN_DOM = false; 80810 80811 /* Decide if a DOM `DocumentFragment` should be returned, instead of a html 80812 * string (or a TrustedHTML object if Trusted Types are supported) */ 80813 var RETURN_DOM_FRAGMENT = false; 80814 80815 /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM 80816 * `Node` is imported into the current `Document`. If this flag is not enabled the 80817 * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by 80818 * DOMPurify. */ 80819 var RETURN_DOM_IMPORT = false; 80820 80821 /* Output should be free from DOM clobbering attacks? */ 80822 var SANITIZE_DOM = true; 80823 80824 /* Keep element content when removing element? */ 80825 var KEEP_CONTENT = true; 80826 80827 /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead 80828 * of importing it into a new Document and returning a sanitized copy */ 80829 var IN_PLACE = false; 80830 80831 /* Allow usage of profiles like html, svg and mathMl */ 80832 var USE_PROFILES = {}; 80833 80834 /* Tags to ignore content of when KEEP_CONTENT is true */ 80835 var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']); 80836 80837 /* Tags that are safe for data: URIs */ 80838 var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']); 80839 80840 /* Attributes safe for values like "javascript:" */ 80841 var URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']); 80842 80843 /* Keep a reference to config to pass to hooks */ 80844 var CONFIG = null; 80845 80846 /* Ideally, do not touch anything below this line */ 80847 /* ______________________________________________ */ 80848 80849 var formElement = document.createElement('form'); 80850 80851 /** 80852 * _parseConfig 80853 * 80854 * @param {Object} cfg optional config literal 80855 */ 80856 // eslint-disable-next-line complexity 80857 var _parseConfig = function _parseConfig(cfg) { 80858 if (CONFIG && CONFIG === cfg) { 80859 return; 80860 } 80861 80862 /* Shield configuration object from tampering */ 80863 if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') { 80864 cfg = {}; 80865 } 80866 80867 /* Set configuration parameters */ 80868 ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS; 80869 ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR; 80870 FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {}; 80871 FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {}; 80872 USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false; 80873 ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true 80874 ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true 80875 ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false 80876 SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false 80877 SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false 80878 WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false 80879 RETURN_DOM = cfg.RETURN_DOM || false; // Default false 80880 RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false 80881 RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false 80882 FORCE_BODY = cfg.FORCE_BODY || false; // Default false 80883 SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true 80884 KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true 80885 IN_PLACE = cfg.IN_PLACE || false; // Default false 80886 80887 IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1; 80888 80889 if (SAFE_FOR_TEMPLATES) { 80890 ALLOW_DATA_ATTR = false; 80891 } 80892 80893 if (RETURN_DOM_FRAGMENT) { 80894 RETURN_DOM = true; 80895 } 80896 80897 /* Parse profile info */ 80898 if (USE_PROFILES) { 80899 ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text))); 80900 ALLOWED_ATTR = []; 80901 if (USE_PROFILES.html === true) { 80902 addToSet(ALLOWED_TAGS, html); 80903 addToSet(ALLOWED_ATTR, html$1); 80904 } 80905 80906 if (USE_PROFILES.svg === true) { 80907 addToSet(ALLOWED_TAGS, svg); 80908 addToSet(ALLOWED_ATTR, svg$1); 80909 addToSet(ALLOWED_ATTR, xml); 80910 } 80911 80912 if (USE_PROFILES.svgFilters === true) { 80913 addToSet(ALLOWED_TAGS, svgFilters); 80914 addToSet(ALLOWED_ATTR, svg$1); 80915 addToSet(ALLOWED_ATTR, xml); 80916 } 80917 80918 if (USE_PROFILES.mathMl === true) { 80919 addToSet(ALLOWED_TAGS, mathMl); 80920 addToSet(ALLOWED_ATTR, mathMl$1); 80921 addToSet(ALLOWED_ATTR, xml); 80922 } 80923 } 80924
80925 /* Merge configuration parameters */ 80926 if (cfg.ADD_TAGS) { 80927 if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) { 80928 ALLOWED_TAGS = clone(ALLOWED_TAGS); 80929 } 80930 80931 addToSet(ALLOWED_TAGS, cfg.ADD_TAGS); 80932 } 80933 80934 if (cfg.ADD_ATTR) { 80935 if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) { 80936 ALLOWED_ATTR = clone(ALLOWED_ATTR); 80937 } 80938 80939 addToSet(ALLOWED_ATTR, cfg.ADD_ATTR); 80940 } 80941 80942 if (cfg.ADD_URI_SAFE_ATTR) { 80943 addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR); 80944 } 80945 80946 /* Add #text in case KEEP_CONTENT is set to true */ 80947 if (KEEP_CONTENT) { 80948 ALLOWED_TAGS['#text'] = true; 80949 } 80950 80951 /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */ 80952 if (WHOLE_DOCUMENT) { 80953 addToSet(ALLOWED_TAGS, ['html', 'head', 'body']); 80954 } 80955 80956 /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */ 80957 if (ALLOWED_TAGS.table) { 80958 addToSet(ALLOWED_TAGS, ['tbody']); 80959 } 80960 80961 // Prevent further manipulation of configuration. 80962 // Not available in IE8, Safari 5, etc. 80963 if (freeze) { 80964 freeze(cfg); 80965 } 80966 80967 CONFIG = cfg; 80968 }; 80969 80970 /** 80971 * _forceRemove 80972 * 80973 * @param {Node} node a DOM node 80974 */ 80975 var _forceRemove = function _forceRemove(node) { 80976 DOMPurify.removed.push({ element: node }); 80977 try { 80978 node.parentNode.removeChild(node); 80979 } catch (error) { 80980 node.outerHTML = emptyHTML; 80981 } 80982 }; 80983 80984 /** 80985 * _removeAttribute 80986 * 80987 * @param {String} name an Attribute name 80988 * @param {Node} node a DOM node 80989 */ 80990 var _removeAttribute = function _removeAttribute(name, node) { 80991 try { 80992 DOMPurify.removed.push({ 80993 attribute: node.getAttributeNode(name), 80994 from: node 80995 }); 80996 } catch (error) { 80997 DOMPurify.removed.push({ 80998 attribute: null, 80999 from: node 81000 }); 81001 } 81002 81003 node.removeAttribute(name); 81004 }; 81005 81006 /** 81007 * _initDocument 81008 * 81009 * @param {String} dirty a string of dirty markup 81010 * @return {Document} a DOM, filled with the dirty markup 81011 */ 81012 var _initDocument = function _initDocument(dirty) { 81013 /* Create a HTML document */ 81014 var doc = void 0; 81015 var leadingWhitespace = void 0; 81016 81017 if (FORCE_BODY) { 81018 dirty = '<remove></remove>' + dirty; 81019 } else { 81020 /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */ 81021 var matches = dirty.match(/^[\s]+/); 81022 leadingWhitespace = matches && matches[0]; 81023 if (leadingWhitespace) { 81024 dirty = dirty.slice(leadingWhitespace.length); 81025 } 81026 } 81027 81028 /* Use DOMParser to workaround Firefox bug (see comment below) */ 81029 if (useDOMParser) { 81030 try { 81031 doc = new DOMParser().parseFromString(dirty, 'text/html'); 81032 } catch (error) {} 81033 } 81034 81035 /* Remove title to fix a mXSS bug in older MS Edge */ 81036 if (removeTitle) { 81037 addToSet(FORBID_TAGS, ['title']); 81038 } 81039 81040 /* Otherwise use createHTMLDocument, because DOMParser is unsafe in 81041 Safari (see comment below) */ 81042 if (!doc || !doc.documentElement) { 81043 doc = implementation.createHTMLDocument(''); 81044 var _doc = doc, 81045 body = _doc.body; 81046 81047 body.parentNode.removeChild(body.parentNode.firstElementChild); 81048 body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; 81049 } 81050 81051 if (leadingWhitespace) { 81052 doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null); 81053 } 81054 81055 /* Work on whole document or just its body */ 81056 return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0]; 81057 }; 81058 81059 // Firefox uses a different parser for innerHTML rather than 81060 // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631) 81061 // which means that you *must* use DOMParser, otherwise the output may 81062 // not be safe if used in a document.write context later. 81063 // 81064 // So we feature detect the Firefox bug and use the DOMParser if necessary. 81065 // 81066 // MS Edge, in older versions, is affected by an mXSS behavior. The second 81067 // check tests for the behavior and fixes it if necessary. 81068 if (DOMPurify.isSupported) { 81069 (function () { 81070 try { 81071 var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">'); 81072 if (doc.querySelector('svg img')) { 81073 useDOMParser = true; 81074 } 81075 } catch (error) {} 81076 })(); 81077 81078 (function () {
81079 try { 81080 var doc = _initDocument('<x/><title></title><img>'); 81081 if (doc.querySelector('title').innerHTML.match(/<\/title/)) { 81082 removeTitle = true; 81083 } 81084 } catch (error) {} 81085 })(); 81086 } 81087 81088 /** 81089 * _createIterator 81090 * 81091 * @param {Document} root document/fragment to create iterator for 81092 * @return {Iterator} iterator instance 81093 */ 81094 var _createIterator = function _createIterator(root) { 81095 return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () { 81096 return NodeFilter.FILTER_ACCEPT; 81097 }, false); 81098 }; 81099 81100 /** 81101 * _isClobbered 81102 * 81103 * @param {Node} elm element to check for clobbering attacks 81104 * @return {Boolean} true if clobbered, false if safe 81105 */ 81106 var _isClobbered = function _isClobbered(elm) { 81107 if (elm instanceof Text || elm instanceof Comment) { 81108 return false; 81109 } 81110 81111 if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') { 81112 return true; 81113 } 81114 81115 return false; 81116 }; 81117 81118 /** 81119 * _isNode 81120 * 81121 * @param {Node} obj object to check whether it's a DOM node 81122 * @return {Boolean} true is object is a DOM node 81123 */ 81124 var _isNode = function _isNode(obj) { 81125 return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string'; 81126 }; 81127 81128 /** 81129 * _executeHook 81130 * Execute user configurable hooks 81131 * 81132 * @param {String} entryPoint Name of the hook's entry point 81133 * @param {Node} currentNode node to work on with the hook 81134 * @param {Object} data additional hook parameters 81135 */ 81136 var _executeHook = function _executeHook(entryPoint, currentNode, data) { 81137 if (!hooks[entryPoint]) { 81138 return; 81139 } 81140 81141 hooks[entryPoint].forEach(function (hook) { 81142 hook.call(DOMPurify, currentNode, data, CONFIG); 81143 }); 81144 }; 81145 81146 /** 81147 * _sanitizeElements 81148 * 81149 * @protect nodeName 81150 * @protect textContent 81151 * @protect removeChild 81152 * 81153 * @param {Node} currentNode to check for permission to exist 81154 * @return {Boolean} true if node was killed, false if left alive 81155 */ 81156 // eslint-disable-next-line complexity 81157 var _sanitizeElements = function _sanitizeElements(currentNode) { 81158 var content = void 0; 81159 81160 /* Execute a hook if present */ 81161 _executeHook('beforeSanitizeElements', currentNode, null); 81162 81163 /* Check if element is clobbered or can clobber */ 81164 if (_isClobbered(currentNode)) { 81165 _forceRemove(currentNode); 81166 return true; 81167 } 81168 81169 /* Now let's check the element's type and name */ 81170 var tagName = currentNode.nodeName.toLowerCase(); 81171 81172 /* Execute a hook if present */ 81173 _executeHook('uponSanitizeElement', currentNode, { 81174 tagName: tagName, 81175 allowedTags: ALLOWED_TAGS 81176 }); 81177 81178 /* Remove element if anything forbids its presence */ 81179 if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) { 81180 /* Keep content except for black-listed elements */ 81181 if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') { 81182 try { 81183 var htmlToInsert = currentNode.innerHTML; 81184 currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert); 81185 } catch (error) {} 81186 } 81187 81188 _forceRemove(currentNode); 81189 return true; 81190 } 81191 81192 /* Remove in case a noscript/noembed XSS is suspected */ 81193 if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) { 81194 _forceRemove(currentNode); 81195 return true; 81196 } 81197 81198 if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) { 81199 _forceRemove(currentNode); 81200 return true; 81201 } 81202 81203 /* Convert markup to cover jQuery behavior */ 81204 if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) { 81205 DOMPurify.removed.push({ element: currentNode.cloneNode() }); 81206 if (currentNode.innerHTML) { 81207 currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '<'); 81208 } else { 81209 currentNode.innerHTML = currentNode.textContent.replace(/</g, '<'); 81210 } 81211 } 81212 81213 /* Sanitize element content to be template-safe */ 81214 if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) { 81215 /* Get the element's text content */ 81216 content = currentNode.textContent; 81217 content = content.replace(MUSTACHE_EXPR$$1, ' '); 81218 content = content.replace(ERB_EXPR$$1, ' '); 81219 if (currentNode.textContent !== content) { 81220 DOMPurify.removed.push({ element: currentNode.cloneNode() }); 81221 currentNode.textContent = content; 81222 } 81223 } 81224 81225 /* Execute a hook if present */ 81226 _executeHook('afterSanitizeElements', currentNode, null); 81227 81228 return false;
81229 }; 81230 81231 /** 81232 * _isValidAttribute 81233 * 81234 * @param {string} lcTag Lowercase tag name of containing element. 81235 * @param {string} lcName Lowercase attribute name. 81236 * @param {string} value Attribute value. 81237 * @return {Boolean} Returns true if `value` is valid, otherwise false. 81238 */ 81239 // eslint-disable-next-line complexity 81240 var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) { 81241 /* Make sure attribute cannot clobber */ 81242 if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) { 81243 return false; 81244 } 81245 81246 /* Allow valid data-* attributes: At least one character after "-" 81247 (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) 81248 XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) 81249 We don't need to check the value; it's always URI safe. */ 81250 if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) { 81251 // This attribute is safe 81252 } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) { 81253 // This attribute is safe 81254 /* Otherwise, check the name is permitted */ 81255 } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) { 81256 return false; 81257 81258 /* Check value is safe. First, is attr inert? If so, is safe */ 81259 } else if (URI_SAFE_ATTRIBUTES[lcName]) { 81260 // This attribute is safe 81261 /* Check no script, data or unknown possibly unsafe URI 81262 unless we know URI values are safe for that attribute */ 81263 } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) { 81264 // This attribute is safe 81265 /* Keep image data URIs alive if src/xlink:href is allowed */ 81266 /* Further prevent gadget XSS for dynamically built script tags */ 81267 } else if ((lcName === 'src' || lcName === 'xlink:href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) { 81268 // This attribute is safe 81269 /* Allow unknown protocols: This provides support for links that 81270 are handled by protocol handlers which may be unknown ahead of 81271 time, e.g. fb:, spotify: */ 81272 } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) { 81273 // This attribute is safe 81274 /* Check for binary attributes */ 81275 // eslint-disable-next-line no-negated-condition 81276 } else if (!value) { 81277 // Binary attributes are safe at this point 81278 /* Anything else, presume unsafe, do not add it back */ 81279 } else { 81280 return false; 81281 } 81282 81283 return true; 81284 }; 81285 81286 /** 81287 * _sanitizeAttributes 81288 * 81289 * @protect attributes 81290 * @protect nodeName 81291 * @protect removeAttribute 81292 * @protect setAttribute 81293 * 81294 * @param {Node} currentNode to sanitize 81295 */ 81296 var _sanitizeAttributes = function _sanitizeAttributes(currentNode) { 81297 var attr = void 0; 81298 var value = void 0; 81299 var lcName = void 0; 81300 var idAttr = void 0; 81301 var l = void 0; 81302 /* Execute a hook if present */ 81303 _executeHook('beforeSanitizeAttributes', currentNode, null); 81304 81305 var attributes = currentNode.attributes; 81306 81307 /* Check if we have attributes; if not we might have a text node */ 81308 81309 if (!attributes) { 81310 return; 81311 } 81312 81313 var hookEvent = { 81314 attrName: '', 81315 attrValue: '', 81316 keepAttr: true, 81317 allowedAttributes: ALLOWED_ATTR 81318 }; 81319 l = attributes.length; 81320 81321 /* Go backwards over all attributes; safely remove bad ones */ 81322 while (l--) { 81323 attr = attributes[l]; 81324 var _attr = attr, 81325 name = _attr.name, 81326 namespaceURI = _attr.namespaceURI; 81327 81328 value = attr.value.trim(); 81329 lcName = name.toLowerCase(); 81330 81331 /* Execute a hook if present */ 81332 hookEvent.attrName = lcName; 81333 hookEvent.attrValue = value; 81334 hookEvent.keepAttr = true; 81335 _executeHook('uponSanitizeAttribute', currentNode, hookEvent); 81336 value = hookEvent.attrValue; 81337 81338 /* Remove attribute */ 81339 // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to 81340 // remove a "name" attribute from an <img> tag that has an "id" 81341 // attribute at the time. 81342 if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) { 81343 idAttr = attributes.id; 81344 attributes = apply(arraySlice, attributes, []); 81345 _removeAttribute('id', currentNode); 81346 _removeAttribute(name, currentNode); 81347 if (attributes.indexOf(idAttr) > l) { 81348 currentNode.setAttribute('id', idAttr.value); 81349 } 81350 } else if ( 81351 // This works around a bug in Safari, where input[type=file] 81352 // cannot be dynamically set after type has been removed 81353 currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) { 81354 continue; 81355 } else { 81356 // This avoids a crash in Safari v9.0 with double-ids. 81357 // The trick is to first set the id to be empty and then to 81358 // remove the attribute 81359 if (name === 'id') { 81360 currentNode.setAttribute(name, ''); 81361 } 81362 81363 _removeAttribute(name, currentNode); 81364 } 81365 81366 /* Did the hooks approve of the attribute? */ 81367 if (!hookEvent.keepAttr) { 81368 continue; 81369 } 81370 81371 /* Sanitize attribute content to be template-safe */ 81372 if (SAFE_FOR_TEMPLATES) { 81373 value = value.replace(MUSTACHE_EXPR$$1, ' '); 81374 value = value.replace(ERB_EXPR$$1, ' '); 81375 } 81376 81377 /* Is `value` valid for this attribute? */ 81378 var lcTag = currentNode.nodeName.toLowerCase(); 81379 if (!_isValidAttribute(lcTag, lcName, value)) { 81380 continue; 81381 } 81382 81383 /* Handle invalid data-* attribute set by try-catching it */
vendor: 4,719 bytes, lines 81384-81535
81384 try { 81385 if (namespaceURI) { 81386 currentNode.setAttributeNS(namespaceURI, name, value); 81387 } else { 81388 /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */ 81389 currentNode.setAttribute(name, value); 81390 } 81391 81392 DOMPurify.removed.pop(); 81393 } catch (error) {} 81394 } 81395 81396 /* Execute a hook if present */ 81397 _executeHook('afterSanitizeAttributes', currentNode, null); 81398 }; 81399 81400 /** 81401 * _sanitizeShadowDOM 81402 * 81403 * @param {DocumentFragment} fragment to iterate over recursively 81404 */ 81405 var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) { 81406 var shadowNode = void 0; 81407 var shadowIterator = _createIterator(fragment); 81408 81409 /* Execute a hook if present */ 81410 _executeHook('beforeSanitizeShadowDOM', fragment, null); 81411 81412 while (shadowNode = shadowIterator.nextNode()) { 81413 /* Execute a hook if present */ 81414 _executeHook('uponSanitizeShadowNode', shadowNode, null); 81415 81416 /* Sanitize tags and elements */ 81417 if (_sanitizeElements(shadowNode)) { 81418 continue; 81419 } 81420 81421 /* Deep shadow DOM detected */ 81422 if (shadowNode.content instanceof DocumentFragment) { 81423 _sanitizeShadowDOM(shadowNode.content); 81424 } 81425 81426 /* Check attributes, sanitize if necessary */ 81427 _sanitizeAttributes(shadowNode); 81428 } 81429 81430 /* Execute a hook if present */ 81431 _executeHook('afterSanitizeShadowDOM', fragment, null); 81432 }; 81433 81434 /** 81435 * Sanitize 81436 * Public method providing core sanitation functionality 81437 * 81438 * @param {String|Node} dirty string or DOM node 81439 * @param {Object} configuration object 81440 */ 81441 // eslint-disable-next-line complexity 81442 DOMPurify.sanitize = function (dirty, cfg) { 81443 var body = void 0; 81444 var importedNode = void 0; 81445 var currentNode = void 0; 81446 var oldNode = void 0; 81447 var returnNode = void 0; 81448 /* Make sure we have a string to sanitize. 81449 DO NOT return early, as this will return the wrong type if 81450 the user has requested a DOM object rather than a string */ 81451 if (!dirty) { 81452 dirty = '<!-->'; 81453 } 81454 81455 /* Stringify, in case dirty is an object */ 81456 if (typeof dirty !== 'string' && !_isNode(dirty)) { 81457 // eslint-disable-next-line no-negated-condition 81458 if (typeof dirty.toString !== 'function') { 81459 throw new TypeError('toString is not a function'); 81460 } else { 81461 dirty = dirty.toString(); 81462 if (typeof dirty !== 'string') { 81463 throw new TypeError('dirty is not a string, aborting'); 81464 } 81465 } 81466 } 81467 81468 /* Check we can run. Otherwise fall back or ignore */ 81469 if (!DOMPurify.isSupported) { 81470 if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') { 81471 if (typeof dirty === 'string') { 81472 return window.toStaticHTML(dirty); 81473 } 81474 81475 if (_isNode(dirty)) { 81476 return window.toStaticHTML(dirty.outerHTML); 81477 } 81478 } 81479 81480 return dirty; 81481 } 81482 81483 /* Assign config vars */ 81484 if (!SET_CONFIG) { 81485 _parseConfig(cfg); 81486 } 81487 81488 /* Clean up removed elements */ 81489 DOMPurify.removed = []; 81490 81491 if (IN_PLACE) { 81492 /* No special handling necessary for in-place sanitization */ 81493 } else if (dirty instanceof Node) { 81494 /* If dirty is a DOM element, append to an empty document to avoid 81495 elements being stripped by the parser */ 81496 body = _initDocument('<!-->'); 81497 importedNode = body.ownerDocument.importNode(dirty, true); 81498 if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') { 81499 /* Node is already a body, use as is */ 81500 body = importedNode; 81501 } else { 81502 // eslint-disable-next-line unicorn/prefer-node-append 81503 body.appendChild(importedNode); 81504 } 81505 } else { 81506 /* Exit directly if we have nothing to do */ 81507 if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) { 81508 return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty; 81509 } 81510 81511 /* Initialize the document to work on */ 81512 body = _initDocument(dirty); 81513 81514 /* Check we have a DOM node from the data */ 81515 if (!body) { 81516 return RETURN_DOM ? null : emptyHTML; 81517 } 81518 } 81519 81520 /* Remove first element node (ours) if FORCE_BODY is set */ 81521 if (body && FORCE_BODY) { 81522 _forceRemove(body.firstChild); 81523 } 81524 81525 /* Get node iterator */ 81526 var nodeIterator = _createIterator(IN_PLACE ? dirty : body); 81527 81528 /* Now start iterating over the created document */ 81529 while (currentNode = nodeIterator.nextNode()) { 81530 /* Fix IE's strange behavior with manipulated textNodes #89 */ 81531 if (currentNode.nodeType === 3 && currentNode === oldNode) { 81532 continue; 81533 } 81534 81535 /* Sanitize tags and elements */
81536 if (_sanitizeElements(currentNode)) { 81537 continue; 81538 } 81539 81540 /* Shadow DOM detected, sanitize it */ 81541 if (currentNode.content instanceof DocumentFragment) { 81542 _sanitizeShadowDOM(currentNode.content); 81543 } 81544 81545 /* Check attributes, sanitize if necessary */ 81546 _sanitizeAttributes(currentNode); 81547 81548 oldNode = currentNode; 81549 } 81550 81551 oldNode = null; 81552 81553 /* If we sanitized `dirty` in-place, return it. */ 81554 if (IN_PLACE) { 81555 return dirty; 81556 } 81557 81558 /* Return sanitized string or DOM */ 81559 if (RETURN_DOM) { 81560 if (RETURN_DOM_FRAGMENT) { 81561 returnNode = createDocumentFragment.call(body.ownerDocument); 81562 81563 while (body.firstChild) { 81564 // eslint-disable-next-line unicorn/prefer-node-append 81565 returnNode.appendChild(body.firstChild); 81566 } 81567 } else { 81568 returnNode = body; 81569 } 81570 81571 if (RETURN_DOM_IMPORT) { 81572 /* AdoptNode() is not used because internal state is not reset 81573 (e.g. the past names map of a HTMLFormElement), this is safe 81574 in theory but we would rather not risk another attack vector. 81575 The state that is cloned by importNode() is explicitly defined 81576 by the specs. */ 81577 returnNode = importNode.call(originalDocument, returnNode, true); 81578 } 81579 81580 return returnNode; 81581 } 81582 81583 var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML; 81584 81585 /* Sanitize final string template-safe */ 81586 if (SAFE_FOR_TEMPLATES) { 81587 serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' '); 81588 serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' '); 81589 } 81590 81591 return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML; 81592 }; 81593 81594 /** 81595 * Public method to set the configuration once 81596 * setConfig 81597 * 81598 * @param {Object} cfg configuration object 81599 */ 81600 DOMPurify.setConfig = function (cfg) { 81601 _parseConfig(cfg); 81602 SET_CONFIG = true; 81603 }; 81604 81605 /** 81606 * Public method to remove the configuration 81607 * clearConfig 81608 * 81609 */ 81610 DOMPurify.clearConfig = function () { 81611 CONFIG = null; 81612 SET_CONFIG = false; 81613 }; 81614 81615 /** 81616 * Public method to check if an attribute value is valid. 81617 * Uses last set config, if any. Otherwise, uses config defaults. 81618 * isValidAttribute 81619 * 81620 * @param {string} tag Tag name of containing element. 81621 * @param {string} attr Attribute name. 81622 * @param {string} value Attribute value. 81623 * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false. 81624 */ 81625 DOMPurify.isValidAttribute = function (tag, attr, value) { 81626 /* Initialize shared config vars if necessary. */ 81627 if (!CONFIG) { 81628 _parseConfig({}); 81629 } 81630 81631 var lcTag = tag.toLowerCase(); 81632 var lcName = attr.toLowerCase(); 81633 return _isValidAttribute(lcTag, lcName, value); 81634 }; 81635 81636 /** 81637 * AddHook 81638 * Public method to add DOMPurify hooks 81639 * 81640 * @param {String} entryPoint entry point for the hook to add 81641 * @param {Function} hookFunction function to execute 81642 */ 81643 DOMPurify.addHook = function (entryPoint, hookFunction) { 81644 if (typeof hookFunction !== 'function') { 81645 return; 81646 } 81647 81648 hooks[entryPoint] = hooks[entryPoint] || []; 81649 hooks[entryPoint].push(hookFunction); 81650 }; 81651 81652 /** 81653 * RemoveHook 81654 * Public method to remove a DOMPurify hook at a given entryPoint 81655 * (pops it from the stack of hooks if more are present) 81656 * 81657 * @param {String} entryPoint entry point for the hook to remove 81658 */ 81659 DOMPurify.removeHook = function (entryPoint) { 81660 if (hooks[entryPoint]) { 81661 hooks[entryPoint].pop(); 81662 } 81663 }; 81664 81665 /** 81666 * RemoveHooks 81667 * Public method to remove all DOMPurify hooks at a given entryPoint 81668 * 81669 * @param {String} entryPoint entry point for the hooks to remove 81670 */ 81671 DOMPurify.removeHooks = function (entryPoint) { 81672 if (hooks[entryPoint]) { 81673 hooks[entryPoint] = []; 81674 } 81675 }; 81676 81677 /** 81678 * RemoveAllHooks 81679 * Public method to remove all DOMPurify hooks 81680 * 81681 */ 81682 DOMPurify.removeAllHooks = function () { 81683 hooks = {}; 81684 }; 81685 81686 return DOMPurify; 81687} 81688 81689var purify = createDOMPurify(); 81690 81691return purify; 81692 81693}))); 81694//# sourceMappingURL=purify.js.map
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.